@effect-ak/tg-bot-client 1.3.4 → 1.4.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/CHANGELOG.md +14 -0
- package/dist/index.cjs +59 -99
- package/dist/index.d.cts +26 -46
- package/dist/index.d.ts +26 -46
- package/dist/index.js +58 -91
- package/package.json +13 -7
- package/readme.md +11 -262
- package/src/client.ts +56 -16
- package/src/execute.ts +93 -20
- package/src/index.ts +24 -7
- package/test/execute.test.ts +31 -19
- package/test/file.test.ts +6 -4
- package/src/client-file.ts +0 -57
- package/src/const.ts +0 -20
- package/src/errors.ts +0 -18
- package/src/guards.ts +0 -27
- package/src/utils.ts +0 -3
package/test/execute.test.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { describe, expect, vi } from "vitest"
|
|
2
2
|
|
|
3
3
|
import { fixture } from "./fixture"
|
|
4
|
-
import { MESSAGE_EFFECTS } from "~/const"
|
|
5
|
-
import { executeTgBotMethod } from "~/execute"
|
|
6
4
|
|
|
7
5
|
const fetchSpy = vi.spyOn(global, "fetch")
|
|
8
6
|
|
|
@@ -10,10 +8,10 @@ describe("telegram bot client, execute method", () => {
|
|
|
10
8
|
fixture("send dice", async ({ chat_id, client }) => {
|
|
11
9
|
// skip();
|
|
12
10
|
|
|
13
|
-
const
|
|
11
|
+
const result = await client.execute("send_dice", {
|
|
14
12
|
chat_id,
|
|
15
13
|
emoji: "🎲",
|
|
16
|
-
message_effect_id:
|
|
14
|
+
message_effect_id: "🔥"
|
|
17
15
|
})
|
|
18
16
|
|
|
19
17
|
const url = fetchSpy.mock.calls[0][0] as string
|
|
@@ -21,28 +19,34 @@ describe("telegram bot client, execute method", () => {
|
|
|
21
19
|
|
|
22
20
|
expect(lastPath).toEqual("sendDice")
|
|
23
21
|
|
|
24
|
-
expect(
|
|
22
|
+
expect(result.ok).toBe(true)
|
|
23
|
+
if (result.ok) {
|
|
24
|
+
expect(result.data.chat.id).toBeDefined()
|
|
25
|
+
}
|
|
25
26
|
})
|
|
26
27
|
|
|
27
28
|
fixture("send message", async ({ chat_id, client, skip }) => {
|
|
28
29
|
skip()
|
|
29
30
|
|
|
30
|
-
const
|
|
31
|
+
const result = await client.execute("send_message", {
|
|
31
32
|
chat_id,
|
|
32
33
|
text: "hey again",
|
|
33
|
-
message_effect_id:
|
|
34
|
+
message_effect_id: "🔥"
|
|
34
35
|
})
|
|
35
36
|
|
|
36
|
-
expect(
|
|
37
|
+
expect(result.ok).toBe(true)
|
|
38
|
+
if (result.ok) {
|
|
39
|
+
expect(result.data.chat.id).toBeDefined()
|
|
40
|
+
}
|
|
37
41
|
})
|
|
38
42
|
|
|
39
43
|
fixture("send message with keyboard", async ({ chat_id, client, skip }) => {
|
|
40
44
|
skip()
|
|
41
45
|
|
|
42
|
-
const
|
|
46
|
+
const result = await client.execute("send_message", {
|
|
43
47
|
chat_id,
|
|
44
48
|
text: "hey again!",
|
|
45
|
-
message_effect_id:
|
|
49
|
+
message_effect_id: "🎉",
|
|
46
50
|
reply_markup: {
|
|
47
51
|
inline_keyboard: [
|
|
48
52
|
[
|
|
@@ -57,15 +61,18 @@ describe("telegram bot client, execute method", () => {
|
|
|
57
61
|
}
|
|
58
62
|
})
|
|
59
63
|
|
|
60
|
-
expect(
|
|
64
|
+
expect(result.ok).toBe(true)
|
|
65
|
+
if (result.ok) {
|
|
66
|
+
expect(result.data.chat.id).toBeDefined()
|
|
67
|
+
}
|
|
61
68
|
})
|
|
62
69
|
|
|
63
70
|
fixture("send document", async ({ chat_id, client, skip }) => {
|
|
64
71
|
skip()
|
|
65
72
|
|
|
66
|
-
const
|
|
73
|
+
const result = await client.execute("send_document", {
|
|
67
74
|
chat_id,
|
|
68
|
-
message_effect_id:
|
|
75
|
+
message_effect_id: "🎉",
|
|
69
76
|
document: {
|
|
70
77
|
file_content: Buffer.from("Hello!"),
|
|
71
78
|
file_name: "hello.txt"
|
|
@@ -73,9 +80,11 @@ describe("telegram bot client, execute method", () => {
|
|
|
73
80
|
caption: "simple text file"
|
|
74
81
|
})
|
|
75
82
|
|
|
76
|
-
expect(
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
expect(result.ok).toBe(true)
|
|
84
|
+
if (result.ok) {
|
|
85
|
+
expect(result.data.document?.file_id).toBeDefined()
|
|
86
|
+
expect(result.data.chat.id).toBeDefined()
|
|
87
|
+
}
|
|
79
88
|
})
|
|
80
89
|
|
|
81
90
|
fixture("send message with action", async ({ chat_id, client }) => {
|
|
@@ -86,12 +95,15 @@ describe("telegram bot client, execute method", () => {
|
|
|
86
95
|
|
|
87
96
|
await new Promise((res) => setTimeout(res, 5000))
|
|
88
97
|
|
|
89
|
-
const
|
|
98
|
+
const result = await client.execute("send_message", {
|
|
90
99
|
chat_id,
|
|
91
100
|
text: "hey again with typings",
|
|
92
|
-
message_effect_id:
|
|
101
|
+
message_effect_id: "🔥"
|
|
93
102
|
})
|
|
94
103
|
|
|
95
|
-
expect(
|
|
104
|
+
expect(result.ok).toBe(true)
|
|
105
|
+
if (result.ok) {
|
|
106
|
+
expect(result.data.chat.id).toBeDefined()
|
|
107
|
+
}
|
|
96
108
|
})
|
|
97
109
|
})
|
package/test/file.test.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { fixture } from "./fixture"
|
|
|
4
4
|
|
|
5
5
|
describe("telegram bot client, download file", () => {
|
|
6
6
|
fixture("get file content", async ({ client, chat_id }) => {
|
|
7
|
-
const
|
|
7
|
+
const result = await client.execute("send_document", {
|
|
8
8
|
chat_id,
|
|
9
9
|
document: {
|
|
10
10
|
file_content: Buffer.from("Hello!"),
|
|
@@ -12,12 +12,14 @@ describe("telegram bot client, download file", () => {
|
|
|
12
12
|
}
|
|
13
13
|
})
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
assert(result.ok, "send_document failed")
|
|
16
|
+
|
|
17
|
+
const fileId = result.data.document?.file_id
|
|
16
18
|
|
|
17
19
|
assert(fileId, "file id is null")
|
|
18
20
|
|
|
19
|
-
const
|
|
21
|
+
const fileResult = await client.getFile({ fileId })
|
|
20
22
|
|
|
21
|
-
expect(
|
|
23
|
+
expect(fileResult.ok).toBe(true)
|
|
22
24
|
})
|
|
23
25
|
})
|
package/src/client-file.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { TgBotClientError } from "./errors"
|
|
2
|
-
import type { ExecuteMethod } from "./execute"
|
|
3
|
-
|
|
4
|
-
export interface TgFile {
|
|
5
|
-
readonly content: ArrayBuffer
|
|
6
|
-
readonly file_name: string
|
|
7
|
-
readonly base64String: () => string
|
|
8
|
-
readonly file: () => File
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const getFile = async (params: {
|
|
12
|
-
fileId: string
|
|
13
|
-
config: {
|
|
14
|
-
bot_token: string
|
|
15
|
-
base_url: string
|
|
16
|
-
}
|
|
17
|
-
type?: string
|
|
18
|
-
execute: ExecuteMethod
|
|
19
|
-
}): Promise<TgFile> => {
|
|
20
|
-
const { fileId, config, execute } = params
|
|
21
|
-
const response = await execute("get_file", { file_id: fileId })
|
|
22
|
-
const file_path = response.file_path
|
|
23
|
-
|
|
24
|
-
if (!file_path || file_path.length === 0) {
|
|
25
|
-
throw new TgBotClientError({
|
|
26
|
-
cause: {
|
|
27
|
-
_tag: "UnableToGetFile",
|
|
28
|
-
cause: "File path not defined"
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const file_name = file_path.replaceAll("/", "-")
|
|
34
|
-
const url = `${config.base_url}/file/bot${config.bot_token}/${file_path}`
|
|
35
|
-
|
|
36
|
-
let content: ArrayBuffer
|
|
37
|
-
try {
|
|
38
|
-
content = await fetch(url).then((_) => _.arrayBuffer())
|
|
39
|
-
} catch (cause) {
|
|
40
|
-
throw new TgBotClientError({
|
|
41
|
-
cause: { _tag: "UnableToGetFile", cause }
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const base64String = () => Buffer.from(content).toString("base64")
|
|
46
|
-
const file = () =>
|
|
47
|
-
new File([content], file_name, {
|
|
48
|
-
...(params.type ? { type: params.type } : {})
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
content,
|
|
53
|
-
file_name,
|
|
54
|
-
base64String,
|
|
55
|
-
file
|
|
56
|
-
}
|
|
57
|
-
}
|
package/src/const.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
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/guards.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export interface FileContent {
|
|
2
|
-
file_content: Uint8Array<ArrayBuffer>
|
|
3
|
-
file_name: string
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export const isFileContent = (input: unknown): input is FileContent =>
|
|
7
|
-
typeof input == "object" &&
|
|
8
|
-
input != null &&
|
|
9
|
-
"file_content" in input &&
|
|
10
|
-
input.file_content instanceof Uint8Array &&
|
|
11
|
-
"file_name" in input &&
|
|
12
|
-
typeof input.file_name == "string"
|
|
13
|
-
|
|
14
|
-
export interface TgBotApiResponseSchema {
|
|
15
|
-
ok: boolean
|
|
16
|
-
error_code?: number
|
|
17
|
-
description?: string
|
|
18
|
-
result?: unknown
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const isTgBotApiResponse = (
|
|
22
|
-
input: unknown
|
|
23
|
-
): input is TgBotApiResponseSchema =>
|
|
24
|
-
typeof input == "object" &&
|
|
25
|
-
input != null &&
|
|
26
|
-
"ok" in input &&
|
|
27
|
-
typeof input.ok == "boolean"
|
package/src/utils.ts
DELETED