@codebam/cf-workers-telegram-bot 3.42.0 → 3.45.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/main/src/bot_api.d.ts +10 -0
- package/dist/main/src/bot_api.js +11 -0
- package/dist/main/src/handler.d.ts +12 -0
- package/dist/main/src/handler.js +51 -0
- package/dist/main/src/libs.d.ts +10 -0
- package/dist/main/src/libs.js +30 -0
- package/dist/main/src/main.d.ts +11 -0
- package/dist/main/src/main.js +11 -0
- package/dist/main/src/telegram_api.d.ts +30 -0
- package/dist/main/src/telegram_api.js +153 -0
- package/dist/main/src/telegram_bot.d.ts +26 -0
- package/dist/main/src/telegram_bot.js +152 -0
- package/dist/main/src/telegram_commands.d.ts +19 -0
- package/dist/main/src/telegram_commands.js +16 -0
- package/dist/main/src/telegram_webhook.d.ts +10 -0
- package/dist/main/src/telegram_webhook.js +21 -0
- package/dist/main/src/types.d.ts +220 -0
- package/dist/main/src/types.js +100 -0
- package/dist/main/src/webhook.d.ts +10 -0
- package/dist/main/src/webhook.js +17 -0
- package/dist/worker/src/worker.d.ts +12 -0
- package/dist/worker/src/worker.js +53 -0
- package/package.json +3 -3
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import Handler from "./handler";
|
|
3
|
+
import { Commands, Config, Update, Webhook } from "./types";
|
|
4
|
+
export default class BotApi {
|
|
5
|
+
commands: Commands;
|
|
6
|
+
webhook: Config["webhook"];
|
|
7
|
+
handler: Handler;
|
|
8
|
+
update: (update: Update) => Promise<Response>;
|
|
9
|
+
constructor(commands: Commands, webhook: Webhook, handler: Handler);
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import BotApi from "./bot_api";
|
|
3
|
+
import { PartialConfig } from "./types";
|
|
4
|
+
export default class Handler {
|
|
5
|
+
configs: PartialConfig[];
|
|
6
|
+
constructor(configs: PartialConfig[]);
|
|
7
|
+
getResponse: (_request?: Request, _bot?: BotApi) => Promise<Response>;
|
|
8
|
+
postResponse: (_request?: Request, _bot?: BotApi) => Promise<Response>;
|
|
9
|
+
responses: Record<string, (_request?: Request, _bot?: BotApi) => Promise<Response>>;
|
|
10
|
+
getAccessKeys: (configs: PartialConfig[]) => Promise<Record<string, any> | Record<string, never>>;
|
|
11
|
+
handle: (request: Request) => Promise<Response>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import BotApi from "./bot_api";
|
|
2
|
+
import { sha256, log } from "./libs";
|
|
3
|
+
import { Config, Webhook, localhost, } from "./types";
|
|
4
|
+
export default class Handler {
|
|
5
|
+
configs;
|
|
6
|
+
constructor(configs) {
|
|
7
|
+
this.configs = configs;
|
|
8
|
+
}
|
|
9
|
+
getResponse = async (_request, _bot) => {
|
|
10
|
+
this.getAccessKeys(this.configs).then((access_keys) => Object.keys(access_keys).forEach((key) => log(`${access_keys[key].bot_name} ${new URL(_request?.url ?? localhost).href}${key}`)));
|
|
11
|
+
if (_bot?.webhook.token) {
|
|
12
|
+
return _bot.webhook.process(new URL(_request?.url ?? localhost));
|
|
13
|
+
}
|
|
14
|
+
return this.responses.default();
|
|
15
|
+
};
|
|
16
|
+
postResponse = async (_request, _bot) => {
|
|
17
|
+
const bot = _bot ??
|
|
18
|
+
new BotApi({}, new Webhook(localhost, "", localhost), new Handler([new Config()]));
|
|
19
|
+
if (bot.webhook.token) {
|
|
20
|
+
const request = _request ?? new Request("");
|
|
21
|
+
return (request
|
|
22
|
+
.json()
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
+
.then((update) => bot.update(update)));
|
|
25
|
+
}
|
|
26
|
+
return this.responses.default();
|
|
27
|
+
};
|
|
28
|
+
responses = {
|
|
29
|
+
GET: this.getResponse,
|
|
30
|
+
POST: this.postResponse,
|
|
31
|
+
default: () => new Promise(() => new Response()),
|
|
32
|
+
};
|
|
33
|
+
getAccessKeys = async (configs
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
|
+
) => Promise.all(configs.map((bot_config) => sha256(bot_config.webhook?.token ?? "").then((hash) => [
|
|
36
|
+
hash,
|
|
37
|
+
bot_config,
|
|
38
|
+
]))).then((result) => Object.fromEntries(result));
|
|
39
|
+
// handles the request
|
|
40
|
+
handle = async (request) => this.getAccessKeys(this.configs).then((access_keys) => {
|
|
41
|
+
if (Object.keys(this.responses).includes(request.method)) {
|
|
42
|
+
return this.responses[request.method](request, new access_keys[new URL(request.url).pathname.substring(1)].api({
|
|
43
|
+
...new Config(),
|
|
44
|
+
url: new URL(new URL(request.url).origin),
|
|
45
|
+
handler: this,
|
|
46
|
+
...access_keys[new URL(request.url).pathname.substring(1)],
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
return this.responses.default();
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
export declare const sha256: (text: string) => Promise<string>;
|
|
3
|
+
export declare const prettyJSON: (obj: unknown) => string;
|
|
4
|
+
export declare const JSONResponse: (obj: unknown, status?: number) => Response;
|
|
5
|
+
export declare const log: (obj: any) => any;
|
|
6
|
+
export declare const preTagString: (str: string) => string;
|
|
7
|
+
export declare const addSearchParams: (url: URL, params?: Record<string, string>) => URL;
|
|
8
|
+
export declare const responseToJSON: (response: Response) => Promise<Record<string, unknown>>;
|
|
9
|
+
export declare const undefinedEmpty: <T>(obj: T) => T[];
|
|
10
|
+
export declare const fetch_json: (url: URL) => Promise<Response>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const sha256 = async (text) => crypto.subtle
|
|
2
|
+
.digest("SHA-256", new TextEncoder().encode(text))
|
|
3
|
+
.then((array_buffer) => Array.from(new Uint8Array(array_buffer))
|
|
4
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
5
|
+
.join(""));
|
|
6
|
+
// format json with line indents and newlines
|
|
7
|
+
export const prettyJSON = (obj) => JSON.stringify(obj, null, 2);
|
|
8
|
+
// Generate JSON response
|
|
9
|
+
export const JSONResponse = (obj, status = 200) => new Response(prettyJSON(obj), {
|
|
10
|
+
status: status,
|
|
11
|
+
headers: {
|
|
12
|
+
"content-type": "application/json",
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
export const log = (obj) => console.log(obj) === undefined && obj;
|
|
17
|
+
export const preTagString = (str) => `<pre>${str}</pre>`;
|
|
18
|
+
export const addSearchParams = (url, params = {}) => new URL(`${url.origin}${url.pathname}?${new URLSearchParams(Object.entries(Object.fromEntries([
|
|
19
|
+
...Array.from(url.searchParams.entries()),
|
|
20
|
+
...Object.entries(params),
|
|
21
|
+
]))).toString()}`);
|
|
22
|
+
export const responseToJSON = async (response) => response
|
|
23
|
+
.clone()
|
|
24
|
+
.text()
|
|
25
|
+
.then((text) => JSON.parse(text))
|
|
26
|
+
.catch(() => log({ error: "Failed to parse JSON of response" }));
|
|
27
|
+
export const undefinedEmpty = (obj) => (obj === undefined && []) || [obj];
|
|
28
|
+
export const fetch_json = async (url) => fetch(url.href)
|
|
29
|
+
.then((response) => responseToJSON(response))
|
|
30
|
+
.then((json) => JSONResponse(json));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import BotApi from "./bot_api";
|
|
2
|
+
import Handler from "./handler";
|
|
3
|
+
import * as Libs from "./libs";
|
|
4
|
+
import TelegramApi from "./telegram_api";
|
|
5
|
+
import TelegramBot from "./telegram_bot";
|
|
6
|
+
import TelegramCommands from "./telegram_commands";
|
|
7
|
+
import TelegramWebhook from "./telegram_webhook";
|
|
8
|
+
import * as Types from "./types";
|
|
9
|
+
import Webhook from "./webhook";
|
|
10
|
+
import worker from "../../worker/src/worker";
|
|
11
|
+
export { BotApi, Handler, Libs, TelegramApi, TelegramBot, TelegramCommands, TelegramWebhook, Types, Webhook, worker, };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import BotApi from "./bot_api";
|
|
2
|
+
import Handler from "./handler";
|
|
3
|
+
import * as Libs from "./libs";
|
|
4
|
+
import TelegramApi from "./telegram_api";
|
|
5
|
+
import TelegramBot from "./telegram_bot";
|
|
6
|
+
import TelegramCommands from "./telegram_commands";
|
|
7
|
+
import TelegramWebhook from "./telegram_webhook";
|
|
8
|
+
import * as Types from "./types";
|
|
9
|
+
import Webhook from "./webhook";
|
|
10
|
+
import worker from "../../worker/src/worker";
|
|
11
|
+
export { BotApi, Handler, Libs, TelegramApi, TelegramBot, TelegramCommands, TelegramWebhook, Types, Webhook, worker, };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import BotApi from "./bot_api";
|
|
3
|
+
import { Commands, TelegramInlineQueryResult, TelegramUpdate, Webhook, Update } from "./types";
|
|
4
|
+
import Handler from "./handler";
|
|
5
|
+
export default class TelegramApi extends BotApi {
|
|
6
|
+
constructor(commands: Commands, webhook: Webhook, handler: Handler);
|
|
7
|
+
inlineQueryUpdate: (update: TelegramUpdate) => Promise<Response>;
|
|
8
|
+
messageUpdate: (update: TelegramUpdate) => Promise<Response>;
|
|
9
|
+
updates: {
|
|
10
|
+
inline_query: (update: TelegramUpdate) => Promise<Response>;
|
|
11
|
+
message: (update: TelegramUpdate) => Promise<Response>;
|
|
12
|
+
default: Response;
|
|
13
|
+
};
|
|
14
|
+
update: (update: Update) => Promise<Response>;
|
|
15
|
+
greetUsers: (update: TelegramUpdate) => Promise<Response>;
|
|
16
|
+
getCommand: (args: string[]) => string;
|
|
17
|
+
_executeCommand: (update: TelegramUpdate, text: string, args?: string[]) => Promise<any>;
|
|
18
|
+
executeInlineCommand: (update: TelegramUpdate) => Promise<Response>;
|
|
19
|
+
executeCommand: (update: TelegramUpdate) => Promise<Response>;
|
|
20
|
+
answerInlineQuery: (inline_query_id: number, results: TelegramInlineQueryResult[], cache_time?: number) => Promise<Response>;
|
|
21
|
+
sendMessage: (chat_id: number, text: string, parse_mode?: string, disable_web_page_preview?: boolean, disable_notification?: boolean, reply_to_message_id?: number) => Promise<Response>;
|
|
22
|
+
forwardMessage: (chat_id: number, from_chat_id: number, disable_notification: boolean | undefined, message_id: number) => Promise<Response>;
|
|
23
|
+
sendPhoto: (chat_id: number, photo: string, caption?: string, parse_mode?: string, disable_notification?: boolean, reply_to_message_id?: number) => Promise<Response>;
|
|
24
|
+
sendVideo: (chat_id: number, video: Blob, duration?: number, width?: number, height?: number, thumb?: string, caption?: string, parse_mode?: string, supports_streaming?: boolean, disable_notification?: boolean, reply_to_message_id?: number) => Promise<Response>;
|
|
25
|
+
sendAnimation: (chat_id: number, animation: Blob, duration?: number, width?: number, height?: number, thumb?: string, caption?: string, parse_mode?: string, disable_notification?: boolean, reply_to_message_id?: number) => Promise<Response>;
|
|
26
|
+
sendLocation: (chat_id: number, latitude: number, longitude: number, live_period?: number, disable_notification?: boolean, reply_to_message_id?: number) => Promise<Response>;
|
|
27
|
+
sendPoll: (chat_id: number, question: string, options: string[], is_anonymous?: boolean, type?: string, allows_multiple_answers?: boolean, correct_option_id?: number, explanation?: string, explanation_parse_mode?: string, open_period?: number, close_date?: number, is_closed?: boolean, disable_notification?: boolean, reply_to_message_id?: number) => Promise<Response>;
|
|
28
|
+
sendDice: (chat_id: number, emoji?: string, disable_notification?: boolean, reply_to_message_id?: number) => Promise<Response>;
|
|
29
|
+
getUserProfilePhotos: (user_id: number, offset?: number, limit?: number) => Promise<Response>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import BotApi from "./bot_api";
|
|
2
|
+
import { addSearchParams, log, responseToJSON } from "./libs";
|
|
3
|
+
export default class TelegramApi extends BotApi {
|
|
4
|
+
constructor(commands, webhook, handler) {
|
|
5
|
+
super(commands, webhook, handler);
|
|
6
|
+
}
|
|
7
|
+
inlineQueryUpdate = async (update) => this.executeInlineCommand(update).then(async (response) => (await responseToJSON(response)) && response);
|
|
8
|
+
messageUpdate = async (update) => {
|
|
9
|
+
if (typeof (update.message?.text ?? false) === "string") {
|
|
10
|
+
return await this.executeCommand(update).then(async () => await this.greetUsers(update));
|
|
11
|
+
}
|
|
12
|
+
return this.updates.default;
|
|
13
|
+
};
|
|
14
|
+
updates = {
|
|
15
|
+
inline_query: this.inlineQueryUpdate,
|
|
16
|
+
message: this.messageUpdate,
|
|
17
|
+
default: new Response(),
|
|
18
|
+
};
|
|
19
|
+
update = async (update) => (log({ update }) &&
|
|
20
|
+
update.message !== undefined &&
|
|
21
|
+
(await this.updates.message(update))) ||
|
|
22
|
+
(update.inline_query !== undefined &&
|
|
23
|
+
update.inline_query.query !== "" &&
|
|
24
|
+
(await this.updates.inline_query(update))) ||
|
|
25
|
+
this.updates.default;
|
|
26
|
+
// greet new users who join
|
|
27
|
+
greetUsers = async (update) => {
|
|
28
|
+
if (update.message?.new_chat_members !== undefined) {
|
|
29
|
+
return this.sendMessage(update.message.chat.id, `Welcome to ${update.message.chat.title}, ${update.message.from.username}`);
|
|
30
|
+
}
|
|
31
|
+
return this.updates.default;
|
|
32
|
+
};
|
|
33
|
+
getCommand = (args) => args[0]?.split("@")[0];
|
|
34
|
+
// run command passed from executeCommand
|
|
35
|
+
_executeCommand = async (update, text, args = []) => (log({ execute: { text, args } }) &&
|
|
36
|
+
(async (text_args) => ((command) => ((this.commands[command] ||
|
|
37
|
+
log({
|
|
38
|
+
error: `command '${command}' does not exist`,
|
|
39
|
+
})) &&
|
|
40
|
+
this.commands[command]?.(this, update, [...text_args, ...args])) ||
|
|
41
|
+
// run the command
|
|
42
|
+
this.updates.default)(this.getCommand(text_args)))(
|
|
43
|
+
// get the command to run
|
|
44
|
+
text
|
|
45
|
+
.trimStart()
|
|
46
|
+
.replace(/^([^\s]*\s)\s*/gm, "$1")
|
|
47
|
+
.split(" "))) ??
|
|
48
|
+
this.updates.default;
|
|
49
|
+
// execute the inline custom bot commands from bot configurations
|
|
50
|
+
executeInlineCommand = async (update) => ((await this._executeCommand(update, update.inline_query?.query ?? "")) &&
|
|
51
|
+
(await this._executeCommand(update, "inline", update.inline_query?.query.trimStart().split(" ")))) ??
|
|
52
|
+
this.updates.default;
|
|
53
|
+
// execute the custom bot commands from bot configurations
|
|
54
|
+
executeCommand = async (update) => this._executeCommand(update, update.message?.text ?? "") ||
|
|
55
|
+
this.updates.default;
|
|
56
|
+
// trigger answerInlineQuery command of BotAPI
|
|
57
|
+
answerInlineQuery = async (inline_query_id, results, cache_time = 0) => fetch(log(addSearchParams(new URL(`${this.webhook.api.href}/answerInlineQuery`), {
|
|
58
|
+
inline_query_id: inline_query_id.toString(),
|
|
59
|
+
results: JSON.stringify(results),
|
|
60
|
+
cache_time: cache_time.toString(),
|
|
61
|
+
}).href));
|
|
62
|
+
// trigger sendMessage command of BotAPI
|
|
63
|
+
sendMessage = async (chat_id, text, parse_mode = "", disable_web_page_preview = false, disable_notification = false, reply_to_message_id = 0) => fetch(log(addSearchParams(new URL(`${this.webhook.api.href}/sendMessage`), {
|
|
64
|
+
chat_id: chat_id.toString(),
|
|
65
|
+
text,
|
|
66
|
+
parse_mode: parse_mode,
|
|
67
|
+
disable_web_page_preview: disable_web_page_preview.toString(),
|
|
68
|
+
disable_notification: disable_notification.toString(),
|
|
69
|
+
reply_to_message_id: reply_to_message_id.toString(),
|
|
70
|
+
}).href));
|
|
71
|
+
// trigger forwardMessage command of BotAPI
|
|
72
|
+
forwardMessage = async (chat_id, from_chat_id, disable_notification = false, message_id) => fetch(log(addSearchParams(new URL(`${this.webhook.api.href}/sendMessage`), {
|
|
73
|
+
chat_id: chat_id.toString(),
|
|
74
|
+
from_chat_id: from_chat_id.toString(),
|
|
75
|
+
message_id: message_id.toString(),
|
|
76
|
+
disable_notification: disable_notification.toString(),
|
|
77
|
+
}).href));
|
|
78
|
+
// trigger sendPhoto command of BotAPI
|
|
79
|
+
sendPhoto = async (chat_id, photo, caption = "", parse_mode = "", disable_notification = false, reply_to_message_id = 0) => fetch(log(addSearchParams(new URL(`${this.webhook.api.href}/sendPhoto`), {
|
|
80
|
+
chat_id: chat_id.toString(),
|
|
81
|
+
photo,
|
|
82
|
+
caption,
|
|
83
|
+
parse_mode,
|
|
84
|
+
disable_notification: disable_notification.toString(),
|
|
85
|
+
reply_to_message_id: reply_to_message_id.toString(),
|
|
86
|
+
}).href));
|
|
87
|
+
// trigger sendVideo command of BotAPI
|
|
88
|
+
sendVideo = async (chat_id, video, duration = 0, width = 0, height = 0, thumb = "", caption = "", parse_mode = "", supports_streaming = false, disable_notification = false, reply_to_message_id = 0) => fetch(log(addSearchParams(new URL(`${this.webhook.api.href}/sendVideo`), {
|
|
89
|
+
chat_id: chat_id.toString(),
|
|
90
|
+
video: JSON.stringify(video),
|
|
91
|
+
duration: duration.toString(),
|
|
92
|
+
width: width.toString(),
|
|
93
|
+
height: height.toString(),
|
|
94
|
+
thumb: thumb,
|
|
95
|
+
caption: caption,
|
|
96
|
+
parse_mode: parse_mode,
|
|
97
|
+
supports_streaming: supports_streaming.toString(),
|
|
98
|
+
disable_notification: disable_notification.toString(),
|
|
99
|
+
reply_to_message_id: reply_to_message_id.toString(),
|
|
100
|
+
}).href));
|
|
101
|
+
// trigger sendAnimation command of BotAPI
|
|
102
|
+
sendAnimation = async (chat_id, animation, duration = 0, width = 0, height = 0, thumb = "", caption = "", parse_mode = "", disable_notification = false, reply_to_message_id = 0) => fetch(log(addSearchParams(new URL(`${this.webhook.api.href}/sendAnimation`), {
|
|
103
|
+
chat_id: chat_id.toString(),
|
|
104
|
+
animation: JSON.stringify(animation),
|
|
105
|
+
duration: duration.toString(),
|
|
106
|
+
width: width.toString(),
|
|
107
|
+
height: height.toString(),
|
|
108
|
+
thumb,
|
|
109
|
+
caption,
|
|
110
|
+
parse_mode,
|
|
111
|
+
disable_notification: disable_notification.toString(),
|
|
112
|
+
reply_to_message_id: reply_to_message_id.toString(),
|
|
113
|
+
}).href));
|
|
114
|
+
// trigger sendLocation command of BotAPI
|
|
115
|
+
sendLocation = async (chat_id, latitude, longitude, live_period = 0, disable_notification = false, reply_to_message_id = 0) => fetch(log(addSearchParams(new URL(`${this.webhook.api.href}/sendLocation`), {
|
|
116
|
+
chat_id: chat_id.toString(),
|
|
117
|
+
latitude: latitude.toString(),
|
|
118
|
+
longitude: longitude.toString(),
|
|
119
|
+
live_period: live_period.toString(),
|
|
120
|
+
disable_notification: disable_notification.toString(),
|
|
121
|
+
reply_to_message_id: reply_to_message_id.toString(),
|
|
122
|
+
}).href));
|
|
123
|
+
// trigger senPoll command of BotAPI
|
|
124
|
+
sendPoll = async (chat_id, question, options, is_anonymous = false, type = "", allows_multiple_answers = false, correct_option_id = 0, explanation = "", explanation_parse_mode = "", open_period = 0, close_date = 0, is_closed = false, disable_notification = false, reply_to_message_id = 0) => fetch(log(addSearchParams(new URL(`${this.webhook.api.href}/sendPoll`), {
|
|
125
|
+
chat_id: chat_id.toString(),
|
|
126
|
+
question,
|
|
127
|
+
options: options.toString(),
|
|
128
|
+
is_anonymous: is_anonymous.toString(),
|
|
129
|
+
type,
|
|
130
|
+
allows_multiple_answers: allows_multiple_answers.toString(),
|
|
131
|
+
correct_option_id: correct_option_id.toString(),
|
|
132
|
+
explanation: explanation,
|
|
133
|
+
explanation_parse_mode: explanation_parse_mode,
|
|
134
|
+
open_period: open_period.toString(),
|
|
135
|
+
close_date: close_date.toString(),
|
|
136
|
+
is_closed: is_closed.toString(),
|
|
137
|
+
disable_notification: disable_notification.toString(),
|
|
138
|
+
reply_to_message_id: reply_to_message_id.toString(),
|
|
139
|
+
}).href));
|
|
140
|
+
// trigger senDice command of BotAPI
|
|
141
|
+
sendDice = async (chat_id, emoji = "", disable_notification = false, reply_to_message_id = 0) => fetch(log(addSearchParams(new URL(`${this.webhook.api.href}/sendDice`), {
|
|
142
|
+
chat_id: chat_id.toString(),
|
|
143
|
+
emoji,
|
|
144
|
+
disable_notification: disable_notification.toString(),
|
|
145
|
+
reply_to_message_id: reply_to_message_id.toString(),
|
|
146
|
+
}).href));
|
|
147
|
+
// bot api command to get user profile photos
|
|
148
|
+
getUserProfilePhotos = async (user_id, offset = 0, limit = 0) => fetch(log(addSearchParams(new URL(`${this.webhook.api.href}/getUserProfilePhotos`), {
|
|
149
|
+
user_id: user_id.toString(),
|
|
150
|
+
offset: offset.toString(),
|
|
151
|
+
limit: limit.toString(),
|
|
152
|
+
}).href));
|
|
153
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import TelegramApi from "./telegram_api";
|
|
3
|
+
import { TelegramUpdate, Config, Kv } from "./types";
|
|
4
|
+
export default class TelegramBot extends TelegramApi {
|
|
5
|
+
url: URL;
|
|
6
|
+
kv: Kv;
|
|
7
|
+
get_set: KVNamespace;
|
|
8
|
+
constructor(config: Config);
|
|
9
|
+
code: (update: TelegramUpdate) => Promise<Response>;
|
|
10
|
+
duckduckgo: (update: TelegramUpdate, args: string[]) => Promise<Response>;
|
|
11
|
+
kanye: (update: TelegramUpdate) => Promise<Response>;
|
|
12
|
+
joke: (update: TelegramUpdate) => Promise<Response>;
|
|
13
|
+
dog: (update: TelegramUpdate) => Promise<Response>;
|
|
14
|
+
cat: (update: TelegramUpdate) => Promise<Response>;
|
|
15
|
+
bored: (update: TelegramUpdate) => Promise<Response>;
|
|
16
|
+
epoch: (update: TelegramUpdate) => Promise<Response>;
|
|
17
|
+
_get: (update: TelegramUpdate, args: string[]) => Promise<Response>;
|
|
18
|
+
_set: (update: TelegramUpdate, args: string[]) => Promise<Response>;
|
|
19
|
+
_average: (numbers: number[]) => number;
|
|
20
|
+
recursion: (update: TelegramUpdate) => Promise<Response>;
|
|
21
|
+
roll: (update: TelegramUpdate, args: string[]) => Promise<Response>;
|
|
22
|
+
commandList: (update: TelegramUpdate) => Promise<Response>;
|
|
23
|
+
toss: (update: TelegramUpdate) => Promise<Response>;
|
|
24
|
+
ping: (update: TelegramUpdate, args: string[]) => Promise<Response>;
|
|
25
|
+
getChatInfo: (update: TelegramUpdate) => Promise<Response>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { preTagString, prettyJSON, addSearchParams, responseToJSON, } from "./libs";
|
|
2
|
+
import TelegramApi from "./telegram_api";
|
|
3
|
+
import { TelegramInlineQueryResultArticle, TelegramInlineQueryResultPhoto, } from "./types";
|
|
4
|
+
export default class TelegramBot extends TelegramApi {
|
|
5
|
+
url;
|
|
6
|
+
kv;
|
|
7
|
+
get_set;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
super(config.commands, config.webhook, config.handler);
|
|
10
|
+
this.url = config.url;
|
|
11
|
+
this.kv = config.kv;
|
|
12
|
+
this.get_set = config.kv?.get_set;
|
|
13
|
+
}
|
|
14
|
+
// bot command: /code
|
|
15
|
+
code = async (update) => ((url) => (update.inline_query &&
|
|
16
|
+
this.answerInlineQuery(update.inline_query.id, [
|
|
17
|
+
new TelegramInlineQueryResultArticle(url),
|
|
18
|
+
])) ??
|
|
19
|
+
this.sendMessage(update.message?.chat.id ?? 0, url))("https://github.com/codebam/cf-workers-telegram-bot");
|
|
20
|
+
// bot command: /duckduckgo
|
|
21
|
+
duckduckgo = async (update, args) => ((query) => ((duckduckgo_url) => (update.inline_query &&
|
|
22
|
+
query === "" &&
|
|
23
|
+
this.answerInlineQuery(update.inline_query.id, [
|
|
24
|
+
new TelegramInlineQueryResultArticle("https://duckduckgo.com"),
|
|
25
|
+
])) ||
|
|
26
|
+
(update.inline_query &&
|
|
27
|
+
fetch(addSearchParams(new URL("https://api.duckduckgo.com"), {
|
|
28
|
+
q: query,
|
|
29
|
+
format: "json",
|
|
30
|
+
t: "telegram_bot",
|
|
31
|
+
no_redirect: "1",
|
|
32
|
+
}).href).then((response) => response
|
|
33
|
+
.json()
|
|
34
|
+
.then((results) => results)
|
|
35
|
+
.then((ddg_response) => ((instant_answer_url, thumb_url, default_thumb_url = "https://duckduckgo.com/assets/icons/meta/DDG-icon_256x256.png") => this.answerInlineQuery(update.inline_query?.id ?? 0, (instant_answer_url !== "" && [
|
|
36
|
+
new TelegramInlineQueryResultArticle(`${instant_answer_url}\n\n<a href="${addSearchParams(new URL(duckduckgo_url), {
|
|
37
|
+
q: args
|
|
38
|
+
.slice(1)
|
|
39
|
+
.join(" ")
|
|
40
|
+
.replace(/^!\w* /, ""),
|
|
41
|
+
}).href}">Results From DuckDuckGo</a>`, instant_answer_url, "HTML", thumb_url),
|
|
42
|
+
new TelegramInlineQueryResultArticle(duckduckgo_url, duckduckgo_url, "", default_thumb_url),
|
|
43
|
+
]) || [
|
|
44
|
+
new TelegramInlineQueryResultArticle(duckduckgo_url, duckduckgo_url, "", default_thumb_url),
|
|
45
|
+
], 3600 // 1 hour
|
|
46
|
+
))(ddg_response.Redirect || ddg_response.AbstractURL, (ddg_response.Redirect === "" &&
|
|
47
|
+
`https://duckduckgo.com${(ddg_response.Image !== "" && ddg_response.Image) ||
|
|
48
|
+
(ddg_response.RelatedTopics.length !== 0 &&
|
|
49
|
+
ddg_response.RelatedTopics[0].Icon.URL !== "" &&
|
|
50
|
+
ddg_response.RelatedTopics[0].Icon.URL) ||
|
|
51
|
+
"/i/f96d4798.png"}`) ||
|
|
52
|
+
"")))) ||
|
|
53
|
+
this.sendMessage(update.message?.chat.id ?? 0, duckduckgo_url))((query === "" && "https://duckduckgo.com") ||
|
|
54
|
+
addSearchParams(new URL("https://duckduckgo.com"), {
|
|
55
|
+
q: query,
|
|
56
|
+
}).href))(args.slice(1).join(" "));
|
|
57
|
+
// bot command: /kanye
|
|
58
|
+
kanye = async (update) => fetch("https://api.kanye.rest")
|
|
59
|
+
.then((response) => responseToJSON(response))
|
|
60
|
+
.then((json) => ((message) => (update.inline_query !== undefined &&
|
|
61
|
+
this.answerInlineQuery(update.inline_query.id, [
|
|
62
|
+
new TelegramInlineQueryResultArticle(message),
|
|
63
|
+
])) ||
|
|
64
|
+
this.sendMessage(update.message?.chat.id ?? 0, message))(`Kanye says... ${json.quote}`))
|
|
65
|
+
.catch(() => new Response("Failed to parse JSON"));
|
|
66
|
+
// bot command: /joke
|
|
67
|
+
joke = async (update) => fetch("https://v2.jokeapi.dev/joke/Any?safe-mode")
|
|
68
|
+
.then((response) => responseToJSON(response))
|
|
69
|
+
.then((joke) => joke)
|
|
70
|
+
.then((joke_response) => ((message) => (update.inline_query &&
|
|
71
|
+
this.answerInlineQuery(update.inline_query.id, [
|
|
72
|
+
new TelegramInlineQueryResultArticle(message, joke_response.joke ?? joke_response.setup, "HTML"),
|
|
73
|
+
], 0)) ??
|
|
74
|
+
this.sendMessage(update.message?.chat.id ?? 0, message, "HTML"))(joke_response.joke ??
|
|
75
|
+
`${joke_response.setup}\n\n<tg-spoiler>${joke_response.delivery}</tg-spoiler>`));
|
|
76
|
+
// bot command: /dog
|
|
77
|
+
dog = async (update) => fetch("https://shibe.online/api/shibes")
|
|
78
|
+
.then((response) => response.json())
|
|
79
|
+
.then((json) => json)
|
|
80
|
+
.then((shibe_response) => (update.inline_query &&
|
|
81
|
+
this.answerInlineQuery(update.inline_query.id, [new TelegramInlineQueryResultPhoto(shibe_response[0])], 0)) ??
|
|
82
|
+
this.sendPhoto(update.message?.chat.id ?? 0, shibe_response[0]));
|
|
83
|
+
// bot command: /cat
|
|
84
|
+
cat = async (update) => fetch("https://meow.senither.com/v1/random")
|
|
85
|
+
.then((response) => response.json())
|
|
86
|
+
.then((json) => json)
|
|
87
|
+
.then((json) => (update.inline_query &&
|
|
88
|
+
this.answerInlineQuery(update.inline_query.id, [new TelegramInlineQueryResultPhoto(json.data.url)], 0)) ??
|
|
89
|
+
this.sendPhoto(update.message?.chat.id ?? 0, json.data.url));
|
|
90
|
+
// bot command: /bored
|
|
91
|
+
bored = async (update) => fetch("https://boredapi.com/api/activity/")
|
|
92
|
+
.then((response) => responseToJSON(response))
|
|
93
|
+
.then((json) => json)
|
|
94
|
+
.then((bored_response) => (update.inline_query &&
|
|
95
|
+
this.answerInlineQuery(update.inline_query.id, [new TelegramInlineQueryResultArticle(bored_response.activity)], 0)) ??
|
|
96
|
+
this.sendMessage(update.message?.chat.id ?? 0, bored_response.activity));
|
|
97
|
+
// bot command: /epoch
|
|
98
|
+
epoch = async (update) => ((seconds) => (update.inline_query &&
|
|
99
|
+
this.answerInlineQuery(update.inline_query.id, [new TelegramInlineQueryResultArticle(seconds)], 0)) ??
|
|
100
|
+
this.sendMessage(update.message?.chat.id ?? 0, seconds))(Math.floor(Date.now() / 1000).toString());
|
|
101
|
+
// bot command: /get
|
|
102
|
+
_get = async (update, args) => ((key) => this.get_set
|
|
103
|
+
.get(key)
|
|
104
|
+
.then((value) => (update.inline_query &&
|
|
105
|
+
this.answerInlineQuery(update.inline_query.id, [new TelegramInlineQueryResultArticle(value ?? "")], 0)) ??
|
|
106
|
+
this.sendMessage(update.message?.chat.id ?? 0, value ?? "")))(args[1]);
|
|
107
|
+
// bot command: /set
|
|
108
|
+
_set = async (update, args) => {
|
|
109
|
+
const key = args[1];
|
|
110
|
+
const value = args.slice(2).join(" ");
|
|
111
|
+
const message = `set ${key} to ${value}`;
|
|
112
|
+
this.get_set.put(key, value).then(() => {
|
|
113
|
+
if (update.inline_query) {
|
|
114
|
+
return this.answerInlineQuery(update.inline_query.id, [new TelegramInlineQueryResultArticle(message)], 0);
|
|
115
|
+
}
|
|
116
|
+
return this.sendMessage(update.message?.chat.id ?? 0, message);
|
|
117
|
+
});
|
|
118
|
+
return new Response();
|
|
119
|
+
};
|
|
120
|
+
_average = (numbers) => parseFloat((numbers.reduce((prev, cur) => prev + cur, 0) / numbers.length || 0).toFixed(2));
|
|
121
|
+
// bot command: /recursion
|
|
122
|
+
recursion = async (update) => this.sendMessage(update.message?.chat.id ?? 0, "/recursion");
|
|
123
|
+
// .then((response) => responseToJSON(response))
|
|
124
|
+
// .then((result: { ok: boolean; result: { text: string } }) =>
|
|
125
|
+
// this.handler.postResponse(
|
|
126
|
+
// new Request("", {
|
|
127
|
+
// method: "POST",
|
|
128
|
+
// body: JSON.stringify({
|
|
129
|
+
// message: {
|
|
130
|
+
// text: result.result.text,
|
|
131
|
+
// chat: { id: update.message.chat.id },
|
|
132
|
+
// },
|
|
133
|
+
// }),
|
|
134
|
+
// }),
|
|
135
|
+
// this
|
|
136
|
+
// )
|
|
137
|
+
// );
|
|
138
|
+
// bot command: /roll
|
|
139
|
+
roll = async (update, args) => ((outcome, message) => (update.inline_query &&
|
|
140
|
+
this.answerInlineQuery(update.inline_query.id, [
|
|
141
|
+
new TelegramInlineQueryResultArticle(message(update.inline_query.from.username, update.inline_query.from.first_name, outcome)),
|
|
142
|
+
])) ??
|
|
143
|
+
this.sendMessage(update.message?.chat.id ?? 0, message(update.message?.from.username ?? "", update.message?.from.first_name ?? "", outcome)))(Math.floor(Math.random() * (parseInt(args[1]) || 6 - 1 + 1) + 1), (username, first_name, outcome) => `${first_name ?? username} rolled a ${parseInt(args[1]) || 6} sided die. it landed on ${outcome}`);
|
|
144
|
+
// bot command: /commandList
|
|
145
|
+
commandList = async (update) => this.sendMessage(update.message?.chat.id ?? 0, `<pre>${JSON.stringify(Object.keys(this.commands))}</pre>`, "HTML");
|
|
146
|
+
// bot command: /toss
|
|
147
|
+
toss = async (update) => this.sendMessage(update.message?.chat.id ?? 0, Math.floor(Math.random() * 2) == 0 ? "heads" : "tails");
|
|
148
|
+
// bot command: /ping
|
|
149
|
+
ping = async (update, args) => this.sendMessage(update.message?.chat.id ?? 0, args.length === 1 ? "pong" : args.slice(1).join(" "));
|
|
150
|
+
// bot command: /chatInfo
|
|
151
|
+
getChatInfo = async (update) => this.sendMessage(update.message?.chat.id ?? 0, preTagString(prettyJSON(update.message?.chat ?? 0)), "HTML");
|
|
152
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import TelegramBot from "./telegram_bot";
|
|
3
|
+
import { TelegramUpdate } from "./types";
|
|
4
|
+
export default class TelegramCommands {
|
|
5
|
+
static ping: (bot: TelegramBot, update: TelegramUpdate, args: string[]) => Promise<Response>;
|
|
6
|
+
static toss: (bot: TelegramBot, update: TelegramUpdate) => Promise<Response>;
|
|
7
|
+
static epoch: (bot: TelegramBot, update: TelegramUpdate) => Promise<Response>;
|
|
8
|
+
static kanye: (bot: TelegramBot, update: TelegramUpdate) => Promise<Response>;
|
|
9
|
+
static bored: (bot: TelegramBot, update: TelegramUpdate) => Promise<Response>;
|
|
10
|
+
static joke: (bot: TelegramBot, update: TelegramUpdate) => Promise<Response>;
|
|
11
|
+
static dog: (bot: TelegramBot, update: TelegramUpdate) => Promise<Response>;
|
|
12
|
+
static cat: (bot: TelegramBot, update: TelegramUpdate) => Promise<Response>;
|
|
13
|
+
static roll: (bot: TelegramBot, update: TelegramUpdate, args: string[]) => Promise<Response>;
|
|
14
|
+
static _get: (bot: TelegramBot, update: TelegramUpdate, args: string[]) => Promise<Response>;
|
|
15
|
+
static _set: (bot: TelegramBot, update: TelegramUpdate, args: string[]) => Promise<Response>;
|
|
16
|
+
static duckduckgo: (bot: TelegramBot, update: TelegramUpdate, args: string[]) => Promise<Response>;
|
|
17
|
+
static code: (bot: TelegramBot, update: TelegramUpdate) => Promise<Response>;
|
|
18
|
+
static commandList: (bot: TelegramBot, update: TelegramUpdate) => Promise<Response>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default class TelegramCommands {
|
|
2
|
+
static ping = async (bot, update, args) => bot.ping(update, args);
|
|
3
|
+
static toss = async (bot, update) => bot.toss(update);
|
|
4
|
+
static epoch = async (bot, update) => bot.epoch(update);
|
|
5
|
+
static kanye = async (bot, update) => bot.kanye(update);
|
|
6
|
+
static bored = async (bot, update) => bot.bored(update);
|
|
7
|
+
static joke = async (bot, update) => bot.joke(update);
|
|
8
|
+
static dog = async (bot, update) => bot.dog(update);
|
|
9
|
+
static cat = async (bot, update) => bot.cat(update);
|
|
10
|
+
static roll = async (bot, update, args) => bot.roll(update, args);
|
|
11
|
+
static _get = async (bot, update, args) => bot._get(update, args);
|
|
12
|
+
static _set = async (bot, update, args) => bot._set(update, args);
|
|
13
|
+
static duckduckgo = async (bot, update, args) => bot.duckduckgo(update, args);
|
|
14
|
+
static code = async (bot, update) => bot.code(update);
|
|
15
|
+
static commandList = async (bot, update) => bot.commandList(update);
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import Webhook from "./webhook";
|
|
3
|
+
import { WebhookCommands } from "./types";
|
|
4
|
+
export default class TelegramWebhook extends Webhook {
|
|
5
|
+
constructor(api: URL, token: string, url: URL);
|
|
6
|
+
set: (drop_pending_updates?: boolean) => Promise<Response>;
|
|
7
|
+
get: () => Promise<Response>;
|
|
8
|
+
delete: () => Promise<Response>;
|
|
9
|
+
commands: WebhookCommands;
|
|
10
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import Webhook from "./webhook";
|
|
2
|
+
import { sha256, addSearchParams, fetch_json } from "./libs";
|
|
3
|
+
export default class TelegramWebhook extends Webhook {
|
|
4
|
+
constructor(api, token, url) {
|
|
5
|
+
super(api, token, url);
|
|
6
|
+
}
|
|
7
|
+
set = async (drop_pending_updates = true) => sha256(this.token).then((access_key) => fetch_json(addSearchParams(new URL(`${this.api.origin}/setWebhook`), {
|
|
8
|
+
url: new URL(`${this.url.href}${access_key}`).href,
|
|
9
|
+
max_connections: "100",
|
|
10
|
+
allowed_updates: JSON.stringify(["message", "inline_query"]),
|
|
11
|
+
drop_pending_updates: drop_pending_updates.toString(),
|
|
12
|
+
})));
|
|
13
|
+
get = async () => fetch_json(new URL(`${this.api.href}/getWebhookInfo`));
|
|
14
|
+
delete = async () => fetch_json(new URL(`${this.api.href}/deleteWebhook`));
|
|
15
|
+
commands = {
|
|
16
|
+
...this.commands,
|
|
17
|
+
set: this.set,
|
|
18
|
+
get: this.get,
|
|
19
|
+
delete: this.delete,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import BotApi from "./bot_api";
|
|
3
|
+
import Handler from "./handler";
|
|
4
|
+
import TelegramApi from "./telegram_api";
|
|
5
|
+
import Webhook from "./webhook";
|
|
6
|
+
export { Webhook };
|
|
7
|
+
export type Command = (bot: BotApi, update: Update, args?: string[]) => Promise<Response>;
|
|
8
|
+
export type TelegramCommand = (bot: TelegramApi, update: TelegramUpdate, args?: string[]) => Promise<Response>;
|
|
9
|
+
export type Commands = Record<string, Command>;
|
|
10
|
+
export type Kv = Record<string, KVNamespace> | undefined;
|
|
11
|
+
export declare class Config {
|
|
12
|
+
bot_name: string;
|
|
13
|
+
api: object;
|
|
14
|
+
webhook: Webhook;
|
|
15
|
+
commands: Record<string, Command>;
|
|
16
|
+
kv: Kv | undefined;
|
|
17
|
+
url: URL;
|
|
18
|
+
handler: Handler | undefined;
|
|
19
|
+
constructor(config?: PartialConfig);
|
|
20
|
+
}
|
|
21
|
+
export type PartialConfig = {
|
|
22
|
+
bot_name?: string;
|
|
23
|
+
api?: object;
|
|
24
|
+
webhook?: Webhook;
|
|
25
|
+
commands?: Record<string, Command>;
|
|
26
|
+
kv?: Kv | undefined;
|
|
27
|
+
url?: URL;
|
|
28
|
+
handler?: Handler;
|
|
29
|
+
};
|
|
30
|
+
export declare const localhost: URL;
|
|
31
|
+
export declare class WebhookCommands {
|
|
32
|
+
[key: string]: () => Promise<Response>;
|
|
33
|
+
}
|
|
34
|
+
export type Joke = {
|
|
35
|
+
error: boolean;
|
|
36
|
+
category: string;
|
|
37
|
+
type: string;
|
|
38
|
+
setup?: string;
|
|
39
|
+
delivery?: string;
|
|
40
|
+
joke?: string;
|
|
41
|
+
flags: {
|
|
42
|
+
nsfw: boolean;
|
|
43
|
+
religious: boolean;
|
|
44
|
+
political: boolean;
|
|
45
|
+
racist: boolean;
|
|
46
|
+
sexist: boolean;
|
|
47
|
+
explicit: boolean;
|
|
48
|
+
};
|
|
49
|
+
id: number;
|
|
50
|
+
safe: boolean;
|
|
51
|
+
lang: string;
|
|
52
|
+
};
|
|
53
|
+
export type Bored = {
|
|
54
|
+
activity: string;
|
|
55
|
+
type: string;
|
|
56
|
+
participants: number;
|
|
57
|
+
price: number;
|
|
58
|
+
link: string;
|
|
59
|
+
key: string;
|
|
60
|
+
accessibility: 0;
|
|
61
|
+
};
|
|
62
|
+
export type Balance = Record<string, {
|
|
63
|
+
final_balance: number;
|
|
64
|
+
n_tx: number;
|
|
65
|
+
total_received: number;
|
|
66
|
+
}>;
|
|
67
|
+
export type TelegramFrom = {
|
|
68
|
+
first_name: string;
|
|
69
|
+
id: number;
|
|
70
|
+
is_bot: boolean;
|
|
71
|
+
language_code: string;
|
|
72
|
+
username: string;
|
|
73
|
+
};
|
|
74
|
+
export type TelegramChat = {
|
|
75
|
+
id: number;
|
|
76
|
+
type: string;
|
|
77
|
+
title?: string;
|
|
78
|
+
username?: string;
|
|
79
|
+
first_name?: string;
|
|
80
|
+
last_name?: string;
|
|
81
|
+
bio?: string;
|
|
82
|
+
has_private_forwards: boolean;
|
|
83
|
+
description?: string;
|
|
84
|
+
invite_link?: string;
|
|
85
|
+
pinned_message?: TelegramMessage;
|
|
86
|
+
slow_mode_delay?: number;
|
|
87
|
+
message_auto_delete_time?: number;
|
|
88
|
+
has_protected_content?: boolean;
|
|
89
|
+
sticker_set_name?: string;
|
|
90
|
+
can_set_sticker_set?: boolean;
|
|
91
|
+
linked_chat_id?: number;
|
|
92
|
+
};
|
|
93
|
+
export type TelegramUser = {
|
|
94
|
+
id: number;
|
|
95
|
+
is_bot: boolean;
|
|
96
|
+
first_name: string;
|
|
97
|
+
last_name?: string;
|
|
98
|
+
username?: string;
|
|
99
|
+
language_code?: string;
|
|
100
|
+
can_join_groups?: boolean;
|
|
101
|
+
can_read_all_group_messages?: boolean;
|
|
102
|
+
supports_inline_queries: boolean;
|
|
103
|
+
};
|
|
104
|
+
export type TelegramMessageEntity = {
|
|
105
|
+
type: string;
|
|
106
|
+
offset: number;
|
|
107
|
+
length: number;
|
|
108
|
+
url?: string;
|
|
109
|
+
user?: TelegramUser;
|
|
110
|
+
language?: string;
|
|
111
|
+
};
|
|
112
|
+
export type TelegramPhotoSize = {
|
|
113
|
+
file_id: string;
|
|
114
|
+
file_unique_id: string;
|
|
115
|
+
width: number;
|
|
116
|
+
height: number;
|
|
117
|
+
file_size?: number;
|
|
118
|
+
};
|
|
119
|
+
export type TelegramMessage = {
|
|
120
|
+
message_id: number;
|
|
121
|
+
from: TelegramFrom;
|
|
122
|
+
sender_chat?: TelegramChat;
|
|
123
|
+
date: number;
|
|
124
|
+
chat: TelegramChat;
|
|
125
|
+
forward_from?: TelegramUser;
|
|
126
|
+
forward_from_chat?: TelegramChat;
|
|
127
|
+
forward_from_message_id?: number;
|
|
128
|
+
forward_signature?: string;
|
|
129
|
+
forward_sender_name?: string;
|
|
130
|
+
forward_date?: number;
|
|
131
|
+
is_automatic_forward?: boolean;
|
|
132
|
+
reply_to_message?: TelegramMessage;
|
|
133
|
+
via_bot?: TelegramUser;
|
|
134
|
+
edit_date?: number;
|
|
135
|
+
has_protected_content?: boolean;
|
|
136
|
+
media_group_id?: string;
|
|
137
|
+
author_signature?: string;
|
|
138
|
+
text?: string;
|
|
139
|
+
entities?: TelegramMessageEntity[];
|
|
140
|
+
photo?: TelegramPhotoSize[];
|
|
141
|
+
caption?: string;
|
|
142
|
+
caption_entities?: TelegramMessageEntity[];
|
|
143
|
+
new_chat_members?: TelegramUser[];
|
|
144
|
+
left_chat_member?: TelegramUser;
|
|
145
|
+
new_chat_title?: string;
|
|
146
|
+
delete_chat_photo?: boolean;
|
|
147
|
+
group_chat_created?: boolean;
|
|
148
|
+
supergroup_chat_created?: boolean;
|
|
149
|
+
channel_chat_created?: boolean;
|
|
150
|
+
migrate_to_chat_id?: number;
|
|
151
|
+
migrate_from_chat_id?: number;
|
|
152
|
+
pinned_message?: TelegramMessage;
|
|
153
|
+
connected_website?: string;
|
|
154
|
+
};
|
|
155
|
+
export type TelegramInputMessageContent = {
|
|
156
|
+
message_text: string;
|
|
157
|
+
parse_mode: string;
|
|
158
|
+
};
|
|
159
|
+
export type TelegramInlineQuery = {
|
|
160
|
+
chat_type: "sender" | "private" | "group" | "supergroup" | "channel";
|
|
161
|
+
from: TelegramFrom;
|
|
162
|
+
id: number;
|
|
163
|
+
offset: string;
|
|
164
|
+
query: string;
|
|
165
|
+
};
|
|
166
|
+
export declare class Update {
|
|
167
|
+
[key: string]: unknown;
|
|
168
|
+
}
|
|
169
|
+
export declare class TelegramUpdate extends Update {
|
|
170
|
+
update_id: number;
|
|
171
|
+
message?: TelegramMessage;
|
|
172
|
+
edited_message?: TelegramMessage;
|
|
173
|
+
channel_post?: TelegramMessage;
|
|
174
|
+
edited_channel_post?: TelegramMessage;
|
|
175
|
+
inline_query?: TelegramInlineQuery;
|
|
176
|
+
constructor(update: PartialTelegramUpdate);
|
|
177
|
+
}
|
|
178
|
+
export type PartialTelegramUpdate = {
|
|
179
|
+
update_id?: number;
|
|
180
|
+
message?: TelegramMessage;
|
|
181
|
+
edited_message?: TelegramMessage;
|
|
182
|
+
channel_post?: TelegramMessage;
|
|
183
|
+
edited_channel_post?: TelegramMessage;
|
|
184
|
+
inline_query?: TelegramInlineQuery;
|
|
185
|
+
};
|
|
186
|
+
export type TelegramInlineQueryType = "article" | "photo" | "gif" | "mpeg4_gif" | "video" | "audio" | "voice" | "document" | "location" | "venue" | "contact" | "game" | "sticker";
|
|
187
|
+
export declare class TelegramInlineQueryResult {
|
|
188
|
+
type: TelegramInlineQueryType;
|
|
189
|
+
id: string;
|
|
190
|
+
constructor(type: TelegramInlineQueryType);
|
|
191
|
+
}
|
|
192
|
+
export declare class TelegramInlineQueryResultPhoto extends TelegramInlineQueryResult {
|
|
193
|
+
photo_url: string;
|
|
194
|
+
thumb_url: string;
|
|
195
|
+
photo_width?: number;
|
|
196
|
+
photo_height?: number;
|
|
197
|
+
title?: string;
|
|
198
|
+
description?: string;
|
|
199
|
+
caption?: string;
|
|
200
|
+
parse_mode?: string;
|
|
201
|
+
caption_entities?: string;
|
|
202
|
+
constructor(photo: string);
|
|
203
|
+
}
|
|
204
|
+
export declare class TelegramInlineQueryResultArticle extends TelegramInlineQueryResult {
|
|
205
|
+
title: string;
|
|
206
|
+
input_message_content: TelegramInputMessageContent;
|
|
207
|
+
thumb_url: string;
|
|
208
|
+
constructor(content: string, title?: string, parse_mode?: string, thumb_url?: string);
|
|
209
|
+
}
|
|
210
|
+
export type DDGQueryResponse = {
|
|
211
|
+
AbstractSource: string;
|
|
212
|
+
AbstractURL: string;
|
|
213
|
+
Redirect: string;
|
|
214
|
+
Image: string;
|
|
215
|
+
RelatedTopics: {
|
|
216
|
+
Icon: {
|
|
217
|
+
URL: string;
|
|
218
|
+
};
|
|
219
|
+
}[];
|
|
220
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import Webhook from "./webhook";
|
|
2
|
+
export { Webhook };
|
|
3
|
+
export class Config {
|
|
4
|
+
bot_name;
|
|
5
|
+
api;
|
|
6
|
+
webhook;
|
|
7
|
+
commands;
|
|
8
|
+
kv;
|
|
9
|
+
url;
|
|
10
|
+
handler;
|
|
11
|
+
constructor(config = {}) {
|
|
12
|
+
this.bot_name = config.bot_name || "";
|
|
13
|
+
this.api = config.api || {};
|
|
14
|
+
this.webhook = config.webhook || new Webhook(localhost, "", localhost);
|
|
15
|
+
this.commands = config.commands || {};
|
|
16
|
+
this.kv = config.kv;
|
|
17
|
+
this.url = config.url || new URL(localhost);
|
|
18
|
+
this.handler = config.handler;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export const localhost = new URL("http://localhost");
|
|
22
|
+
export class WebhookCommands {
|
|
23
|
+
}
|
|
24
|
+
export class Update {
|
|
25
|
+
}
|
|
26
|
+
export class TelegramUpdate extends Update {
|
|
27
|
+
update_id;
|
|
28
|
+
message;
|
|
29
|
+
edited_message;
|
|
30
|
+
channel_post;
|
|
31
|
+
edited_channel_post;
|
|
32
|
+
inline_query;
|
|
33
|
+
// chosen_inline_result?: TelegramChosenInlineResult;
|
|
34
|
+
// callback_query?: TelegramCallbackQuery;
|
|
35
|
+
// shipping_query?: TelegramShippingQuery;
|
|
36
|
+
// pre_checkout_query?: TelegramPreCheckoutQuery;
|
|
37
|
+
// poll?: TelegramPoll;
|
|
38
|
+
// poll_answer?: TelegramPollAnswer;
|
|
39
|
+
// my_chat_member?: TelegramChatMemberUpdated;
|
|
40
|
+
// chat_member?: TelegramChatMemberUpdated;
|
|
41
|
+
// chat_join_request: TelegramChatJoinRequest;
|
|
42
|
+
constructor(update) {
|
|
43
|
+
super();
|
|
44
|
+
this.update_id = update.update_id || 0;
|
|
45
|
+
this.message = update.message;
|
|
46
|
+
this.edited_message = update.edited_message;
|
|
47
|
+
this.channel_post = update.channel_post;
|
|
48
|
+
this.edited_channel_post = update.edited_channel_post;
|
|
49
|
+
this.inline_query = update.inline_query;
|
|
50
|
+
// chosen_inline_result = update.chosen_inline_result;
|
|
51
|
+
// callback_query = update.callback_query;
|
|
52
|
+
// shipping_query = update.shipping_query;
|
|
53
|
+
// pre_checkout_query = update.pre_checkout_query;
|
|
54
|
+
// poll = update.poll;
|
|
55
|
+
// poll_answer = update.poll_answer;
|
|
56
|
+
// my_chat_member = update.my_chat_member;
|
|
57
|
+
// chat_member = update.chat_member;
|
|
58
|
+
// chat_join_request = update.chat_join_request;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export class TelegramInlineQueryResult {
|
|
62
|
+
type;
|
|
63
|
+
id;
|
|
64
|
+
constructor(type) {
|
|
65
|
+
this.type = type;
|
|
66
|
+
this.id = crypto.randomUUID();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export class TelegramInlineQueryResultPhoto extends TelegramInlineQueryResult {
|
|
70
|
+
photo_url; // must be a jpg
|
|
71
|
+
thumb_url;
|
|
72
|
+
photo_width;
|
|
73
|
+
photo_height;
|
|
74
|
+
title;
|
|
75
|
+
description;
|
|
76
|
+
caption;
|
|
77
|
+
parse_mode;
|
|
78
|
+
caption_entities;
|
|
79
|
+
// reply_markup?: TelegramInlineKeyboardMarkup;
|
|
80
|
+
// input_message_content?: TelegramInputMessageContent;
|
|
81
|
+
constructor(photo) {
|
|
82
|
+
super("photo");
|
|
83
|
+
this.photo_url = photo;
|
|
84
|
+
this.thumb_url = photo;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export class TelegramInlineQueryResultArticle extends TelegramInlineQueryResult {
|
|
88
|
+
title;
|
|
89
|
+
input_message_content;
|
|
90
|
+
thumb_url;
|
|
91
|
+
constructor(content, title = content, parse_mode = "", thumb_url = "") {
|
|
92
|
+
super("article");
|
|
93
|
+
this.title = title;
|
|
94
|
+
this.input_message_content = {
|
|
95
|
+
message_text: content.toString(),
|
|
96
|
+
parse_mode,
|
|
97
|
+
};
|
|
98
|
+
this.thumb_url = thumb_url;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
import { WebhookCommands } from "./types";
|
|
3
|
+
export default class Webhook {
|
|
4
|
+
api: URL;
|
|
5
|
+
token: string;
|
|
6
|
+
url: URL;
|
|
7
|
+
commands: WebhookCommands;
|
|
8
|
+
constructor(api: URL, token: string, url: URL);
|
|
9
|
+
process: (url: URL) => Promise<Response>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { JSONResponse } from "./libs";
|
|
2
|
+
export default class Webhook {
|
|
3
|
+
api;
|
|
4
|
+
token;
|
|
5
|
+
url;
|
|
6
|
+
commands;
|
|
7
|
+
constructor(api, token, url) {
|
|
8
|
+
this.api = api;
|
|
9
|
+
this.token = token;
|
|
10
|
+
this.url = url;
|
|
11
|
+
this.commands = {
|
|
12
|
+
default: () => new Promise(() => JSONResponse({ error: "Invalid command" }, 400)),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
process = async (url) => this.commands[url.searchParams.get("command") ?? ""]?.() ??
|
|
16
|
+
this.commands.default;
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
interface Environment {
|
|
3
|
+
SECRET_TELEGRAM_API_TOKEN: string;
|
|
4
|
+
KV_GET_SET: KVNamespace;
|
|
5
|
+
KV_UID_DATA: KVNamespace;
|
|
6
|
+
SECRET_TELEGRAM_API_TOKEN2: string;
|
|
7
|
+
SECRET_TELEGRAM_API_TOKEN3: string;
|
|
8
|
+
}
|
|
9
|
+
declare const _default: {
|
|
10
|
+
fetch: (request: Request, env: Environment) => Promise<Response>;
|
|
11
|
+
};
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { TelegramCommands, Handler, TelegramWebhook, TelegramBot, } from "../../main/src/main";
|
|
2
|
+
export default {
|
|
3
|
+
fetch: async (request, env) => new Handler([
|
|
4
|
+
{
|
|
5
|
+
bot_name: "cf-workers-telegram-bot",
|
|
6
|
+
api: TelegramBot,
|
|
7
|
+
webhook: new TelegramWebhook(new URL(`https://api.telegram.org/bot${env.SECRET_TELEGRAM_API_TOKEN}`), env.SECRET_TELEGRAM_API_TOKEN, new URL(new URL(request.url).origin)),
|
|
8
|
+
commands: {
|
|
9
|
+
"/ping": TelegramCommands.ping,
|
|
10
|
+
"/toss": TelegramCommands.toss,
|
|
11
|
+
"/epoch": TelegramCommands.epoch,
|
|
12
|
+
"/kanye": TelegramCommands.kanye,
|
|
13
|
+
"/bored": TelegramCommands.bored,
|
|
14
|
+
"/joke": TelegramCommands.joke,
|
|
15
|
+
"/dog": TelegramCommands.dog,
|
|
16
|
+
"/cat": TelegramCommands.cat,
|
|
17
|
+
"/roll": TelegramCommands.roll,
|
|
18
|
+
"/get": TelegramCommands._get,
|
|
19
|
+
"/set": TelegramCommands._set,
|
|
20
|
+
"/duckduckgo": TelegramCommands.duckduckgo,
|
|
21
|
+
"/code": TelegramCommands.code,
|
|
22
|
+
"/commands": TelegramCommands.commandList,
|
|
23
|
+
"/help": TelegramCommands.commandList,
|
|
24
|
+
"/start": TelegramCommands.commandList,
|
|
25
|
+
},
|
|
26
|
+
kv: { get_set: env.KV_GET_SET, uid_data: env.KV_UID_DATA },
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
bot_name: "@duckduckbot",
|
|
30
|
+
api: TelegramBot,
|
|
31
|
+
webhook: new TelegramWebhook(new URL(`https://api.telegram.org/bot${env.SECRET_TELEGRAM_API_TOKEN2}`), env.SECRET_TELEGRAM_API_TOKEN2, new URL(new URL(request.url).origin)),
|
|
32
|
+
commands: {
|
|
33
|
+
inline: TelegramCommands.duckduckgo,
|
|
34
|
+
"/duckduckgo": TelegramCommands.duckduckgo,
|
|
35
|
+
"/code": TelegramCommands.code,
|
|
36
|
+
"/commands": TelegramCommands.commandList,
|
|
37
|
+
"/start": TelegramCommands.commandList,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
bot_name: "@ddggbot",
|
|
42
|
+
api: TelegramBot,
|
|
43
|
+
webhook: new TelegramWebhook(new URL(`https://api.telegram.org/bot${env.SECRET_TELEGRAM_API_TOKEN3}`), env.SECRET_TELEGRAM_API_TOKEN3, new URL(new URL(request.url).origin)),
|
|
44
|
+
commands: {
|
|
45
|
+
inline: TelegramCommands.duckduckgo,
|
|
46
|
+
"/duckduckgo": TelegramCommands.duckduckgo,
|
|
47
|
+
"/code": TelegramCommands.code,
|
|
48
|
+
"/commands": TelegramCommands.commandList,
|
|
49
|
+
"/start": TelegramCommands.commandList,
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
]).handle(request),
|
|
53
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codebam/cf-workers-telegram-bot",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.45.0",
|
|
4
4
|
"description": "serverless telegram bot on cf workers",
|
|
5
5
|
"main": "./dist/main/src/main.js",
|
|
6
6
|
"module": "./dist/main/src/main.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"url": "https://github.com/codebam/cf-workers-telegram-bot.git"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"worker": "^3.
|
|
32
|
+
"worker": "^3.44.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@cloudflare/workers-types": "^4.20230215.0",
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"prettier": "^2.8.4",
|
|
40
40
|
"typescript": "^4.9.5"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "be956bd06e29a9fea3daf4d85153533544188c0c"
|
|
43
43
|
}
|