@puregram/hear
Version:
simple implementation of hearing messages system for puregram
131 lines (130 loc) • 5.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HearManager = void 0;
require("reflect-metadata");
const puregram_1 = require("puregram");
const middleware_io_1 = require("middleware-io");
const helpers_1 = require("./helpers");
class HearManager {
constructor() {
this.composer = puregram_1.Composer.builder();
this.fallbackHandler = middleware_io_1.skipMiddleware;
this.recompose();
}
get length() {
return this.composer.length;
}
get middleware() {
return (context, next) => this.composed(context, next);
}
hear(hearConditions, handler) {
const rawConditions = !Array.isArray(hearConditions)
? [hearConditions]
: hearConditions;
const hasConditions = rawConditions.every(Boolean);
if (!hasConditions) {
throw new Error('condition should be not empty');
}
if (typeof handler !== 'function') {
throw new TypeError('handler must be a function');
}
let textCondition = false;
let functionCondition = false;
const conditions = rawConditions.map((condition) => {
if (typeof condition === 'object' && !(condition instanceof RegExp)) {
functionCondition = true;
const entries = Object.entries(condition)
.map(([path, value]) => [(0, helpers_1.splitPath)(path), (0, helpers_1.unifyCondition)(value)]);
return (text, context) => (entries.every(([selectors, callback]) => {
const value = (0, helpers_1.getObjectValue)(context, selectors);
return callback(value, context);
}));
}
if (typeof condition === 'function') {
functionCondition = true;
return condition;
}
textCondition = true;
if (condition instanceof RegExp) {
return (text, context) => {
if (text === undefined) {
return false;
}
const passed = condition.test(text);
if (passed) {
context.$match = text.match(condition);
}
return passed;
};
}
const stringCondition = String(condition);
return (text) => text === stringCondition;
});
const needText = textCondition && !functionCondition;
this.composer.use((context, next) => {
var _a, _b, _c;
if (needText && !((_a = context.hasText) === null || _a === void 0 ? void 0 : _a.call(context)) && !((_b = context.hasCaption) === null || _b === void 0 ? void 0 : _b.call(context))) {
return next();
}
const text = (_c = context.text) !== null && _c !== void 0 ? _c : context.caption;
const hasSome = conditions.some(condition => condition(text, context));
return hasSome
? handler(context, next)
: next();
});
this.recompose();
return this;
}
command(command, handler) {
if (!command) {
throw new Error('command should not be empty');
}
if (typeof handler !== 'function') {
throw new TypeError('handler must be a function');
}
this.composer.use((context, next) => {
var _a, _b, _c, _d;
if (!((_a = context.hasText) === null || _a === void 0 ? void 0 : _a.call(context)) && !((_b = context.hasCaption) === null || _b === void 0 ? void 0 : _b.call(context))) {
return next();
}
const text = (_c = context.text) !== null && _c !== void 0 ? _c : context.caption;
const firstWord = text.split(/\s/)[0];
// INFO: starts with a '/' followed by a bunch of symbols (might have '@' and a bunch of symbols ending with 'bot')
// INFO: /foo_bar@username_bot
if (/^\/\w+(?:@\w+bot)?/.test(firstWord)) {
// INFO: 't' for 'text'
const [tCommandRaw, tUsername] = firstWord.split('@');
const hasUsername = tUsername !== undefined;
const contextHasBotInfo = ((_d = context.telegram.bot) === null || _d === void 0 ? void 0 : _d.username) !== undefined;
// INFO: we have '@<username>' part but we don't have info about our bot
if (hasUsername && !contextHasBotInfo) {
return next();
}
// INFO: we have '@<username>' part but usernames do not match
if (hasUsername && tUsername.toLowerCase() !== context.telegram.bot.username.toLowerCase()) {
return next();
}
// INFO: since command starts with '/' and we don't have that in [command] we need to slice that
const tCommand = tCommandRaw.slice(1);
if (tCommand !== command) {
return next();
}
return handler(context, next);
}
});
this.recompose();
return this;
}
/** A handler that is called when handlers are not found */
onFallback(handler) {
this.fallbackHandler = handler;
this.recompose();
return this;
}
recompose() {
this.composed = this.composer.clone()
.use(this.fallbackHandler)
.compose();
}
}
exports.HearManager = HearManager;