Skip to content

Commit

Permalink
refactor: 使用Proxy为TelegramBotAPI添加实现
Browse files Browse the repository at this point in the history
  • Loading branch information
TBXark committed Aug 24, 2024
1 parent 7fb7071 commit 594848a
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 80 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"eslint": "^9.8.0",
"eslint-plugin-format": "^0.1.2",
"rollup-plugin-cleanup": "^3.2.1",
"telegram-bot-api-types": "^7.9.1",
"telegram-bot-api-types": "^7.9.2",
"typescript": "^5.5.4",
"vite": "^5.2.10",
"vite-plugin-checker": "^0.7.2",
Expand Down
4 changes: 2 additions & 2 deletions src/route/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { commandsBindScope, commandsDocument } from '../telegram/command';
import type { RouterRequest } from '../utils/router';
import { Router } from '../utils/router';
import type { Telegram } from '../types/telegram';
import { TelegramBotAPI } from '../telegram/api/api';
import { createTelegramBotAPI } from '../telegram/api/api';
import { errorToString, makeResponse200, renderHTML } from './utils';

const helpLink = 'https://github.com/TBXark/ChatGPT-Telegram-Workers/blob/master/doc/en/DEPLOY.md';
Expand All @@ -23,7 +23,7 @@ async function bindWebHookAction(request: RouterRequest): Promise<Response> {
const hookMode = API_GUARD ? 'safehook' : 'webhook';
const scope = commandsBindScope();
for (const token of ENV.TELEGRAM_AVAILABLE_TOKENS) {
const api = new TelegramBotAPI(token);
const api = createTelegramBotAPI(token);
const url = `https://${domain}/telegram/${token.trim()}/${hookMode}`;
const id = token.split(':')[0];
result[id] = {};
Expand Down
96 changes: 36 additions & 60 deletions src/telegram/api/api.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
import type { Telegram } from '../../types/telegram';

export class TelegramBotAPI implements
Telegram.SendMessageRequest,
Telegram.EditMessageTextRequest,
Telegram.SendPhotoRequest,
Telegram.SendChatActionRequest,
Telegram.SetWebhookRequest,
Telegram.DeleteWebhookRequest,
Telegram.SetMyCommandsRequest,
Telegram.GetMeRequest,
Telegram.GetFileRequest,
Telegram.GetChatAdministratorsRequest,
Telegram.GetUpdatesRequest {
class APIClientBase {
readonly token: string;
readonly baseURL: string = `https://api.telegram.org/`;

constructor(token: string, baseURL?: string) {
this.token = token;
if (baseURL) {
this.baseURL = baseURL;
}
}

static from(token: string, baseURL?: string): TelegramBotAPI {
return new TelegramBotAPI(token, baseURL);
}

jsonRequest<T>(method: Telegram.TelegramBotMethod, params: T): Promise<Response> {
private jsonRequest<T>(method: Telegram.BotMethod, params: T): Promise<Response> {
return fetch(`${this.baseURL}bot${this.token}/${method}`, {
method: 'POST',
headers: {
Expand All @@ -36,7 +20,7 @@ export class TelegramBotAPI implements
});
}

formDataRequest<T>(method: Telegram.TelegramBotMethod, params: T): Promise<Response> {
private formDataRequest<T>(method: Telegram.BotMethod, params: T): Promise<Response> {
const formData = new FormData();
for (const key in params) {
const value = params[key];
Expand All @@ -56,47 +40,39 @@ export class TelegramBotAPI implements
});
}

sendMessage(params: Telegram.SendMessageParams): Promise<Response> {
return this.jsonRequest('sendMessage', params);
}

editMessageText(params: Telegram.EditMessageTextParams): Promise<Response> {
return this.jsonRequest('editMessageText', params);
}

sendPhoto(params: Telegram.SendPhotoParams): Promise<Response> {
return this.formDataRequest('sendPhoto', params);
}

sendChatAction(params: Telegram.SendChatActionParams): Promise<Response> {
return this.jsonRequest('sendChatAction', params);
}

setWebhook(params: Telegram.SetWebhookParams): Promise<Response> {
return this.jsonRequest('setWebhook', params);
}

deleteWebhook(): Promise<Response> {
return this.jsonRequest('deleteWebhook', {});
}

setMyCommands(params: Telegram.SetMyCommandsParams): Promise<Response> {
return this.jsonRequest('setMyCommands', params);
}

getMe(): Promise<Response> {
return this.jsonRequest('getMe', {});
}

getFile(params: Telegram.GetFileParams): Promise<Response> {
return this.jsonRequest('getFile', params);
}

getChatAdministrators(params: Telegram.GetChatAdministratorsParams): Promise<Response> {
return this.jsonRequest('getChatAdministrators', params);
request<T>(method: Telegram.BotMethod, params: T): Promise<Response> {
for (const key in params) {
if (params[key] instanceof File || params[key] instanceof Blob) {
return this.formDataRequest(method, params);
}
}
return this.jsonRequest(method, params);
}
}

getUpdates(params: Telegram.GetUpdatesParams): Promise<Response> {
return this.jsonRequest('getUpdates', params);
}
export type TelegramBotAPI = APIClientBase &
Telegram.SendMessageRequest &
Telegram.EditMessageTextRequest &
Telegram.SendPhotoRequest &
Telegram.SendChatActionRequest &
Telegram.SetWebhookRequest &
Telegram.DeleteWebhookRequest &
Telegram.SetMyCommandsRequest &
Telegram.GetMeRequest &
Telegram.GetFileRequest &
Telegram.GetChatAdministratorsRequest &
Telegram.GetUpdatesRequest;

export function createTelegramBotAPI(token: string): TelegramBotAPI {
const client = new APIClientBase(token);
return new Proxy(client, {
get(target, prop, receiver) {
if (prop in target) {
return Reflect.get(target, prop, receiver);
}
return (...args: any[]) => {
return target.request(prop as Telegram.BotMethod, args[0]);
};
},
}) as TelegramBotAPI;
}
4 changes: 2 additions & 2 deletions src/telegram/command/auth.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { WorkerContext } from '../../config/context';
import { DATABASE } from '../../config/env';
import { TelegramBotAPI } from '../api/api';
import { createTelegramBotAPI } from '../api/api';
import type { Telegram, TelegramAPISuccess } from '../../types/telegram';

export async function loadChatRoleWithContext(context: WorkerContext): Promise<string | null> {
Expand All @@ -22,7 +22,7 @@ export async function loadChatRoleWithContext(context: WorkerContext): Promise<s
console.error(e);
}
if (groupAdmin === null || !Array.isArray(groupAdmin) || groupAdmin.length === 0) {
const result = await TelegramBotAPI.from(token).getChatAdministrators({ chat_id: chatId }).then(res => res.json()).catch(() => null) as TelegramAPISuccess<Telegram.ChatMemberAdministrator[]>;
const result = await createTelegramBotAPI(token).getChatAdministrators({ chat_id: chatId }).then(res => res.json()).catch(() => null) as TelegramAPISuccess<Telegram.ChatMemberAdministrator[]>;
if (result == null) {
return null;
}
Expand Down
6 changes: 3 additions & 3 deletions src/telegram/command/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { isTelegramChatTypeGroup } from '../utils/utils';
import type { HistoryItem, HistoryModifierResult } from '../../agent/types';
import { chatWithLLM } from '../handler/chat';
import { loadChatLLM, loadImageGen } from '../../agent/agents';
import { TelegramBotAPI } from '../api/api';
import { createTelegramBotAPI } from '../api/api';
import type { CommandHandler } from './type';

export const COMMAND_AUTH_CHECKER = {
Expand Down Expand Up @@ -47,7 +47,7 @@ export class ImgCommandHandler implements CommandHandler {
return sendMessageToTelegramWithContext(context)(ENV.I18N.command.help.img);
}
try {
const api = TelegramBotAPI.from(context.SHARE_CONTEXT.currentBotToken);
const api = createTelegramBotAPI(context.SHARE_CONTEXT.currentBotToken);
const agent = loadImageGen(context.USER_CONFIG);
if (!agent) {
return sendMessageToTelegramWithContext(context)('ERROR: Image generator not found');
Expand Down Expand Up @@ -115,7 +115,7 @@ class BaseNewCommandHandler {
selective: true,
};
}
return TelegramBotAPI.from(context.SHARE_CONTEXT.currentBotToken).sendMessage(params);
return createTelegramBotAPI(context.SHARE_CONTEXT.currentBotToken).sendMessage(params);
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/telegram/handler/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { WorkerContext } from '../../config/context';
import { sendMessageToTelegramWithContext } from '../utils/send';
import type { Telegram, TelegramAPISuccess } from '../../types/telegram';
import { uploadImageToTelegraph } from '../../utils/image';
import { TelegramBotAPI } from '../api/api';
import { createTelegramBotAPI } from '../api/api';
import type { MessageHandler } from './type';

export async function chatWithLLM(params: LLMChatRequestParams, context: WorkerContext, modifier: HistoryModifier | null): Promise<Response> {
Expand All @@ -18,7 +18,7 @@ export async function chatWithLLM(params: LLMChatRequestParams, context: WorkerC
} catch (e) {
console.error(e);
}
const api = TelegramBotAPI.from(context.SHARE_CONTEXT.currentBotToken);
const api = createTelegramBotAPI(context.SHARE_CONTEXT.currentBotToken);
setTimeout(() => api.sendChatAction({
chat_id: context.CURRENT_CHAT_CONTEXT.chat_id,
action: 'typing',
Expand Down Expand Up @@ -100,7 +100,7 @@ export class ChatHandler implements MessageHandler {

if (message.photo && message.photo.length > 0) {
const id = findPhotoFileID(message.photo, ENV.TELEGRAM_PHOTO_SIZE_OFFSET);
const api = TelegramBotAPI.from(context.SHARE_CONTEXT.currentBotToken);
const api = createTelegramBotAPI(context.SHARE_CONTEXT.currentBotToken);
const file = await api.getFile({ file_id: id }).then(res => res.json()) as TelegramAPISuccess<Telegram.File>;
let url = file.result.file_path;
if (url) {
Expand Down
4 changes: 2 additions & 2 deletions src/telegram/handler/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Telegram, TelegramAPISuccess } from '../../types/telegram';
import type { WorkerContext } from '../../config/context';
import { isTelegramChatTypeGroup } from '../utils/utils';
import { ENV } from '../../config/env';
import { TelegramBotAPI } from '../api/api';
import { createTelegramBotAPI } from '../api/api';
import type { MessageHandler } from './type';

function checkMention(content: string, entities: Telegram.MessageEntity[], botName: string, botId: number): {
Expand Down Expand Up @@ -62,7 +62,7 @@ export class GroupMention implements MessageHandler {
// 处理群组消息,过滤掉AT部分
let botName = context.SHARE_CONTEXT.currentBotName;
if (!botName) {
const res = await TelegramBotAPI.from(context.SHARE_CONTEXT.currentBotToken).getMe().then(res => res.json()) as TelegramAPISuccess<User>;
const res = await createTelegramBotAPI(context.SHARE_CONTEXT.currentBotToken).getMe().then(res => res.json()) as TelegramAPISuccess<User>;
botName = res.result.username || null;
context.SHARE_CONTEXT.currentBotName = botName;
}
Expand Down
7 changes: 4 additions & 3 deletions src/telegram/utils/send.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { CurrentChatContext, WorkerContext } from '../../config/context';
import type { Telegram } from '../../types/telegram';
import { TelegramBotAPI } from '../api/api';
import type { TelegramBotAPI } from '../api/api';
import { createTelegramBotAPI } from '../api/api';

async function sendMessage(api: TelegramBotAPI, message: string, token: string, context: CurrentChatContext): Promise<Response> {
if (context?.message_id) {
Expand Down Expand Up @@ -42,7 +43,7 @@ async function sendLongMessage(message: string, token: string, context: CurrentC
const chatContext = context;
const originMessage = message;
const limit = 4096;
const api = TelegramBotAPI.from(token);
const api = createTelegramBotAPI(token);

if (message.length <= limit) {
const resp = await sendMessage(api, message, token, chatContext);
Expand Down Expand Up @@ -83,7 +84,7 @@ export function sendMessageToTelegramWithContext(context: WorkerContext): (messa

export function sendPhotoToTelegramWithContext(context: WorkerContext): (photo: string | Blob) => Promise<Response> {
return async (photo) => {
const api = TelegramBotAPI.from(context.SHARE_CONTEXT.currentBotToken);
const api = createTelegramBotAPI(context.SHARE_CONTEXT.currentBotToken);
const chatContext = context.CURRENT_CHAT_CONTEXT;
const params: Telegram.SendPhotoParams = {
chat_id: chatContext.chat_id,
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2867,10 +2867,10 @@ tapable@^2.2.0:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==

telegram-bot-api-types@^7.9.1:
version "7.9.1"
resolved "https://registry.yarnpkg.com/telegram-bot-api-types/-/telegram-bot-api-types-7.9.1.tgz#2466ba6c3ff028a4b7a2ed3f9a21e86d35ba0a6a"
integrity sha512-aI1jKgB+zs3t9Mbt58tQNc3EGuafuQG/FwJIkBNgU5CYiBa2u4Ona9S6nQbP81isCMyiXvsam+sLpPoxEFULbg==
telegram-bot-api-types@^7.9.2:
version "7.9.2"
resolved "https://registry.yarnpkg.com/telegram-bot-api-types/-/telegram-bot-api-types-7.9.2.tgz#c2952ba4d947939695c404c7e567209eaff3c55d"
integrity sha512-k0VsiOUJwBJy1Lkr43g5QFzmBkiL7rj5BvKOMYe4m6zCHeyomGPoLJV1z1GaC5LeW3jIn6P+5A1+zXYaQX/i1g==

text-table@^0.2.0:
version "0.2.0"
Expand Down

0 comments on commit 594848a

Please sign in to comment.