@apidog/multibot-sdk-ts
Advanced tools
Comparing version 0.3.0 to 0.4.0-experimental-1
@@ -11,3 +11,3 @@ import { IMatcher } from './utils'; | ||
export interface IBot { | ||
request<T>(method: string, params?: object): Promise<T>; | ||
request<T>(method: string, params?: Record<string, unknown>): Promise<T>; | ||
} | ||
@@ -17,5 +17,5 @@ export default abstract class AbstractBot<Config, Update> implements IBot { | ||
protected matcher: IMatcher<Update>; | ||
protected setMatcher(matcher: IMatcher<Update>): void; | ||
protected setMatcher(matcher: IMatcher<Update>): this; | ||
protected abstract getApiEndpoint(method: string): string; | ||
abstract request<T>(method: string, params?: object): Promise<T>; | ||
abstract request<T>(method: string, params?: Record<string, unknown>): Promise<T>; | ||
} |
@@ -6,2 +6,3 @@ "use strict"; | ||
this.matcher = matcher; | ||
return this; | ||
} | ||
@@ -8,0 +9,0 @@ } |
@@ -37,3 +37,3 @@ /// <reference types="node" /> | ||
constructor(config: Config); | ||
protected getApiEndpoint: (method: string) => string; | ||
protected readonly getApiEndpoint: (method: string) => string; | ||
private createFormDataFromParams; | ||
@@ -40,0 +40,0 @@ request: <T>(apiMethod: string, params?: Record<string, unknown>) => Promise<T>; |
@@ -23,3 +23,3 @@ "use strict"; | ||
exports.Bot = void 0; | ||
const axios_1 = require("axios"); | ||
const node_fetch_1 = require("node-fetch"); | ||
const FormData = require("form-data"); | ||
@@ -35,36 +35,2 @@ const fs = require("fs"); | ||
this.getApiEndpoint = (method) => `${this.config.apiUrl}/bot${this.config.secret}/${method}`; | ||
this.createFormDataFromParams = (params) => { | ||
return Object.entries(params).reduce((form, [key, value]) => { | ||
if (value === undefined) { | ||
return form; | ||
} | ||
if (typeof value === 'string' && ['photo', 'video', 'audio', 'document'].includes(key) && !value.startsWith('http') && fs.existsSync(value)) { | ||
value = fs.createReadStream(value); | ||
} | ||
if (value instanceof Buffer || value instanceof fs.ReadStream) { | ||
let filename = 'filename'; // fallback | ||
if ('__filename' in params) { | ||
filename = params.__filename; // user-specified name | ||
} | ||
else if (value instanceof fs.ReadStream && typeof value.path === 'string') { | ||
filename = path.basename(value.path); // file stream path | ||
} | ||
form.append(key, value, { filename }); | ||
return form; | ||
} | ||
switch (typeof value) { | ||
case 'number': | ||
case 'boolean': { | ||
value = String(value); | ||
break; | ||
} | ||
case 'object': { | ||
value = JSON.stringify(value); | ||
break; | ||
} | ||
} | ||
form.append(key, value); | ||
return form; | ||
}, new FormData()); | ||
}; | ||
this.request = (apiMethod, params = {}) => __awaiter(this, void 0, void 0, function* () { | ||
@@ -74,4 +40,10 @@ var _a; | ||
const form = this.createFormDataFromParams(params); | ||
const headers = form.getHeaders(); | ||
const { data, status, statusText } = yield axios_1.default.post(url, form, { headers }); | ||
const request = yield node_fetch_1.default(url, { | ||
method: 'POST', | ||
body: form, | ||
headers: form.getHeaders(), | ||
timeout: 5000, | ||
}); | ||
const data = yield request.json(); | ||
const { status, statusText } = request; | ||
if (data === null || data === void 0 ? void 0 : data.ok) { | ||
@@ -183,2 +155,3 @@ return data.result; | ||
while (this.isPollingActive) { | ||
// eslint-disable-next-line no-await-in-loop | ||
yield this.poll(); | ||
@@ -198,3 +171,3 @@ } | ||
} | ||
resolve(void 0); | ||
resolve(); | ||
response.forEach(this.handleUpdate); | ||
@@ -210,2 +183,36 @@ }); | ||
} | ||
createFormDataFromParams(params) { | ||
return Object.entries(params).reduce((form, [key, value]) => { | ||
if (value === undefined) { | ||
return form; | ||
} | ||
if (typeof value === 'string' && ['photo', 'video', 'audio', 'document'].includes(key) && !value.startsWith('http') && fs.existsSync(value)) { | ||
value = fs.createReadStream(value); | ||
} | ||
if (value instanceof Buffer || value instanceof fs.ReadStream) { | ||
let filename = 'filename'; // fallback | ||
if ('__filename' in params) { | ||
filename = params.__filename; // user-specified name | ||
} | ||
else if (value instanceof fs.ReadStream && typeof value.path === 'string') { | ||
filename = path.basename(value.path); // file stream path | ||
} | ||
form.append(key, value, { filename }); | ||
return form; | ||
} | ||
switch (typeof value) { | ||
case 'number': | ||
case 'boolean': { | ||
value = String(value); | ||
break; | ||
} | ||
case 'object': { | ||
value = JSON.stringify(value); | ||
break; | ||
} | ||
} | ||
form.append(key, value); | ||
return form; | ||
}, new FormData()); | ||
} | ||
} | ||
@@ -212,0 +219,0 @@ exports.Bot = Bot; |
import { Update, Media } from './types'; | ||
import { Matcher, MatchHandle, MatchTest } from '../utils'; | ||
import { Matcher, MatchHandle, MatchRule, MatchTest } from '../utils'; | ||
import { IBot } from '../abstract-bot'; | ||
@@ -57,4 +57,4 @@ import { ArgumentMessage } from '.'; | ||
constructor(bot: IBot); | ||
getMatches: (update: Update) => import("../utils").MatchRule<Update>[]; | ||
getMatches: (update: Update) => MatchRule<Update>[]; | ||
} | ||
export {}; |
@@ -87,3 +87,4 @@ "use strict"; | ||
: false; | ||
};*/ | ||
}; | ||
*/ | ||
const media = (field) => ({ | ||
@@ -115,3 +116,3 @@ test: update => exports.testMessage(update) && field in update.message, | ||
{ type: MatchType.InlineQuery, test: exports.testInlineQuery, handle: exports.handleInlineQuery }, | ||
// { type: MatchType.Exact, test: testExactText, handle: handleExactText }, | ||
// { type: MatchType.Exact, test: testExactText, handle: handleExactText }, | ||
{ type: MatchType.Command, test: exports.testCommand, handle: exports.handleCommand }, | ||
@@ -130,3 +131,3 @@ Object.assign({ type: MatchType.Photo }, media('photo')), | ||
Object.assign({ type: MatchType.Game }, media('game')), | ||
// { type: MatchType.VideoNote, ...media('video_note') }, | ||
// { type: MatchType.VideoNote, ...media('video_note') }, | ||
{ type: MatchType.Media, test: testMedia, handle: handleMedia }, | ||
@@ -133,0 +134,0 @@ ]); |
@@ -47,3 +47,3 @@ import { QuizType } from './media'; | ||
}; | ||
export declare type CallbackGame = object; | ||
export declare type CallbackGame = Record<string, unknown>; | ||
export declare type ForceReplyMarkup = { | ||
@@ -50,0 +50,0 @@ force_reply: boolean; |
import { KeyboardBuilder, AbstractButton } from './abstract'; | ||
import type { Markup, ReplyKeyboard } from '../../types/keyboard'; | ||
import type { ReplyKeyboardButton } from '../../types/keyboard'; | ||
import type { Markup, ReplyKeyboard, ReplyKeyboardButton } from '../../types/keyboard'; | ||
export declare class ReplyKeyboardBuilder extends KeyboardBuilder<ReplyKeyboard, ReplyButton, 'keyboard'> { | ||
@@ -5,0 +4,0 @@ build(): Markup; |
@@ -6,3 +6,3 @@ "use strict"; | ||
for (const char of chars) { | ||
text = text.replace(char, '\\' + char); | ||
text = text.replace(char, `\\${char}`); | ||
} | ||
@@ -9,0 +9,0 @@ return text; |
@@ -23,3 +23,3 @@ import AbstractBot, { IBotPolling } from '../abstract-bot'; | ||
constructor(config: Config); | ||
protected getApiEndpoint: (method: string) => string; | ||
protected readonly getApiEndpoint: (method: string) => string; | ||
request: Request; | ||
@@ -26,0 +26,0 @@ /** |
@@ -23,5 +23,5 @@ "use strict"; | ||
exports.Bot = void 0; | ||
const FormData = require("form-data"); | ||
const node_fetch_1 = require("node-fetch"); | ||
const abstract_bot_1 = require("../abstract-bot"); | ||
const FormData = require("form-data"); | ||
const axios_1 = require("axios"); | ||
const matcher_1 = require("./matcher"); | ||
@@ -53,8 +53,15 @@ class Bot extends abstract_bot_1.default { | ||
const endpoint = this.getApiEndpoint(apiMethod); | ||
const { data, status, statusText } = yield axios_1.default.post(endpoint, form, { | ||
headers: Object.assign({}, (form.getHeaders())) | ||
const request = yield node_fetch_1.default(endpoint, { | ||
method: 'POST', | ||
body: form, | ||
headers: form.getHeaders(), | ||
}); | ||
const data = yield request.json(); | ||
const { status, statusText } = request; | ||
if (status !== 200) { | ||
throw new Error(`Error HTTP ${statusText}`); | ||
} | ||
if ('error' in data) { | ||
throw data.error; | ||
} | ||
return data.response; | ||
@@ -66,5 +73,3 @@ }); | ||
this.isPollingActive = false; | ||
this.getLongPollServer = () => __awaiter(this, void 0, void 0, function* () { | ||
return this.request('groups.getLongPollServer', { group_id: this.config.groupId }); | ||
}); | ||
this.getLongPollServer = () => __awaiter(this, void 0, void 0, function* () { return this.request('groups.getLongPollServer', { group_id: this.config.groupId }); }); | ||
this.startPolling = () => __awaiter(this, void 0, void 0, function* () { | ||
@@ -78,2 +83,3 @@ if (this.isPollingActive) { | ||
while (this.isPollingActive) { | ||
// eslint-disable-next-line no-await-in-loop | ||
yield this.poll(); | ||
@@ -88,3 +94,4 @@ } | ||
this.waitForResponseLongPoll = () => __awaiter(this, void 0, void 0, function* () { | ||
return (yield axios_1.default.get(this.getLongPollUrl())).data; | ||
const request = yield node_fetch_1.default(this.getLongPollUrl()); | ||
return request.json(); | ||
}); | ||
@@ -95,3 +102,3 @@ this.poll = () => __awaiter(this, void 0, void 0, function* () { | ||
this.server.ts = response.ts; | ||
resolve(void 0); | ||
resolve(); | ||
response.updates.forEach(this.handleUpdate); | ||
@@ -98,0 +105,0 @@ }); |
@@ -16,3 +16,3 @@ "use strict"; | ||
const fetcherUser = (message, bot) => (fields) => __awaiter(void 0, void 0, void 0, function* () { return utils_1.getSender(bot, message, fields); }); | ||
const testMessage = update => update.type == 'message_new'; | ||
const testMessage = update => update.type === 'message_new'; | ||
exports.testMessage = testMessage; | ||
@@ -27,8 +27,6 @@ const handleMessage = ({ object }, bot) => { | ||
} | ||
else { | ||
return { | ||
message: object, | ||
getSender: fetcherUser(object, bot), | ||
}; | ||
} | ||
return { | ||
message: object, | ||
getSender: fetcherUser(object, bot), | ||
}; | ||
}; | ||
@@ -47,3 +45,3 @@ exports.handleMessage = handleMessage; | ||
event: update.object, | ||
getUser: () => utils_1.getUser(bot, update.object.user_id) | ||
getUser: () => utils_1.getUser(bot, update.object.user_id), | ||
}); | ||
@@ -50,0 +48,0 @@ exports.handleMessageAllow = handleMessageAllow; |
@@ -51,3 +51,6 @@ /// <reference types="node" /> | ||
error_message: string; | ||
request_params: object[]; | ||
request_params: { | ||
key: string; | ||
value: string; | ||
}[]; | ||
} | ||
@@ -54,0 +57,0 @@ export interface UpdateWrap { |
@@ -9,9 +9,9 @@ export interface Message { | ||
conversation_message_id: number; | ||
fwd_messages: object[]; | ||
geo?: object; | ||
fwd_messages: Record<string, unknown>[]; | ||
geo?: Record<string, unknown>; | ||
random_id?: number; | ||
important: boolean; | ||
attachments: object[]; | ||
attachments: Record<string, unknown>[]; | ||
admin_author_id?: number; | ||
is_hidden?: boolean; | ||
} |
{ | ||
"name": "@apidog/multibot-sdk-ts", | ||
"version": "0.3.0", | ||
"version": "0.4.0-experimental-1", | ||
"description": "Telegram and VK bot SDK for TypeScript", | ||
@@ -16,3 +16,3 @@ "main": "dist/index.js", | ||
"test": "jest", | ||
"lint": "eslint --cache --ext .ts,.tsx src" | ||
"lint": "eslint --cache --ext .ts src" | ||
}, | ||
@@ -27,15 +27,20 @@ "keywords": [ | ||
"dependencies": { | ||
"axios": "0.21.1", | ||
"form-data": "4.0.0" | ||
"form-data": "4.0.0", | ||
"node-fetch": "2.6.1" | ||
}, | ||
"devDependencies": { | ||
"@types/jest": "26.0.20", | ||
"@types/node": "14.14.31", | ||
"@typescript-eslint/eslint-plugin": "4.15.2", | ||
"@typescript-eslint/parser": "4.15.2", | ||
"dotenv": "8.2.0", | ||
"eslint": "7.20.0", | ||
"jest": "26.6.3", | ||
"ts-jest": "26.5.1", | ||
"typescript": "4.1.5" | ||
"@types/jest": "26.0.23", | ||
"@types/node": "15.12.4", | ||
"@types/node-fetch": "2.5.10", | ||
"@typescript-eslint/eslint-plugin": "4.27.0", | ||
"@typescript-eslint/parser": "4.27.0", | ||
"airbnb-style": "2.0.0", | ||
"dotenv": "10.0.0", | ||
"eslint": "7.29.0", | ||
"eslint-config-airbnb": "18.2.1", | ||
"eslint-config-airbnb-typescript": "12.3.1", | ||
"eslint-plugin-import": "2.23.4", | ||
"jest": "27.0.4", | ||
"ts-jest": "27.0.3", | ||
"typescript": "4.3.4" | ||
}, | ||
@@ -42,0 +47,0 @@ "bugs": { |
@@ -9,4 +9,4 @@ # Multibot SDK | ||
### Usage | ||
Example: | ||
### Usage example | ||
Firstly, create instance of `Telegram.Bot`: | ||
```typescript | ||
@@ -19,5 +19,8 @@ import { Telegram } from '@apidog/multibot-sdk-ts'; | ||
}); | ||
``` | ||
#### Handle new messages | ||
```typescript | ||
bot.on(Telegram.MatchType.Message, ({ message, from, chat }) => { | ||
bot.request('sendMessage', { | ||
bot.sendMessage({ | ||
chat_id: chat.id, | ||
@@ -31,21 +34,57 @@ text: `Hello, ${from.first_name}!`, | ||
### Using keyboard builder | ||
#### Build and using keyboards | ||
List of available keyboards: | ||
* ReplyKeyboard; | ||
* InlineKeyboard; | ||
* ForceReply; | ||
* RemoveKeyboard. | ||
* `ReplyKeyboard`; | ||
* `InlineKeyboard`; | ||
* `ForceReply`; | ||
* `RemoveKeyboard`. | ||
#### Example: | ||
```typescript | ||
import { Telegram } from '@apidog/multibot-sdk-ts'; | ||
// create keyboard | ||
const kb = new Telegram.ReplyKeyboardBuilder(); | ||
const kb = new Telegram.ReplyKeyboardBuilder(); | ||
const row = kb.addRow(); // add row | ||
// add row | ||
const row = kb.addRow(); | ||
// add button to row | ||
row.addButton(new Telegram.ReplyButton('Click me!')); | ||
bot.request('sendMessage', { | ||
// ... | ||
bot.sendMessage({ | ||
// ... rest parameters ... | ||
// build keyboard | ||
reply_markup: kb.build(), | ||
}); | ||
``` | ||
#### Upload photo/video/audio/file | ||
Using the example of sending a photo: | ||
```typescript | ||
// 1. URL | ||
const photo: string = 'https://telegram.org/img/t_logo.png'; | ||
// 2. File id | ||
const photo: string = '123456789abcdefghi'; | ||
// 3. Local path | ||
import * as fs from 'fs'; | ||
const photo: string = path.resolve('photo.jpg'); | ||
// 4. Buffer (for example, page = puppeteer.Page) | ||
const photo: Buffer = await page.screenshot(); | ||
// 5. fs.ReadStream | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
const photo: fs.ReadStream = fs.createReadStream(path.resolve('photo.jpg')); | ||
bot.sendPhoto({ | ||
// ... rest parameters ... | ||
// passing one variable of the above | ||
photo, | ||
// you can specify the filename if you are passing Buffer | ||
__filename: '', | ||
}); | ||
``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
193985
144
2882
87
14
5
+ Addednode-fetch@2.6.1
+ Addednode-fetch@2.6.1(transitive)
- Removedaxios@0.21.1
- Removedaxios@0.21.1(transitive)
- Removedfollow-redirects@1.15.9(transitive)