UNPKG

tlgbot

Version:

TLGbot is a javascript framework to create telegram robot application

312 lines (283 loc) 10.4 kB
const that = { storage: undefined, send: undefined, menu: undefined, query: undefined, log: undefined, onmessage, onfile: onmessage, oncommand: onmessage, custom, onquery, onbutton, init } const buttons_names = [] const buttons_keys = [] const spc = "" function init() { const menu = that.menu for (let level in menu) { for (let keys in menu[level]) { if (typeof menu[level][keys].button != "undefined") { if (!buttons_keys.includes(keys)) buttons_keys.push(keys) for (let btn_keys in menu[level][keys].button) { if (!buttons_names.includes(btn_keys)) buttons_names.push(btn_keys) } } } } } function custom(id, input) { return onmessage({ update_id: 0, message: { message_id: 0, from: { id: id, is_bot: false, }, chat: { id: id, type: 'private' }, date: Math.round(new Date() / 1000), text: input } }) } // function check_inline(a1, a2) { // return array1.length === array2.length && a1.every((value, index) => value === a2[index]) // } async function onbutton(data) { const menu = that.menu if (!menu) return const id = data.callback_query.from.id var input = data.callback_query.data.split(spc) try { const user = get_user(data.callback_query.from) var level = get_user_level(menu, user.l) var key = buttons_keys[input[1]] + "$%@-" + buttons_names[input[2]] input = input[0] user.b = input key = parse_key(level, key, menu) var item = parse_item(level, key, id, input, user, key, data) var next_data = await parse_data_item(id, item, input, user, key, data) if (!next_data) throw Error('BOTMENU: data in inline menu is empty: level "' + Object.keys(menu)[Object.values(menu).indexOf(level)] + "\" index \"" + key + '"') parse_button(next_data, key) next_data.message_id = data.callback_query.message.message_id next_data.chat_id = id var method = "answerCallbackQuery" if (item.method) method = item.method if (next_data.method) { method = next_data.method delete next_data.method } if (method == "answerCallbackQuery") next_data.callback_query_id = data.callback_query.id that.send(method, next_data); user.i = key } catch (error) { that.log(error) } } async function onquery(data) { const menu = that.query if (!menu) return const id = data.inline_query.from.id const input = data.inline_query.query.trim() try { const user = get_user(data.inline_query.from) var level = get_user_level(menu, user.l) var key = input if (key == "") { key = "start" } key = parse_key(level, key, menu) var item = parse_item(level, key, id, input, user, key, data) var next_data = await parse_data_item(id, item, input, user, key, data) if (!next_data) throw Error('BOTMENU: data in query menu is empty: level "' + Object.keys(menu)[Object.values(menu).indexOf(level)] + "\" index \"" + key + '"') parse_button(next_data, key) next_data.inline_query_id = data.inline_query.id that.send("answerInlineQuery", next_data); } catch (error) { that.log(error) } } async function onmessage(data) { const menu = that.menu if (data.message.via_bot || data.message.from.is_bot || !menu) return; const id = data.message.from.id const input = data.message.text ? data.message.text.trim() : "" try { const user = get_user(data.message.from) const level = get_user_level(menu, user.l) if (input[0] == "/") { var cmd = parse_cmd(input) var key = parse_key(level, cmd[0], menu, false) var item = parse_item(level, key, id, cmd[1], user, cmd[0], data) var next_data = await parse_data_item(id, item, cmd[1], user, cmd[0], data) if (!next_data) throw Error('BOTMENU: data in menu is not defined: level "' + Object.keys(menu)[Object.values(menu).indexOf(level)] + "\" index \"" + key + '"') } else if (data.message.chat.type == 'private') { var last_item = get_item(level, user.i) var key = await parse_text(id, user, last_item, input, level, menu, data) if (key == false) return key = parse_key(level, key, menu, false) var item = parse_item(level, key, id, input, user, key, data) var next_data = await parse_data_item(id, item, input, user, key, data) } if (!next_data) throw Error('BOTMENU: data in menu is not defined: level "' + Object.keys(menu)[Object.values(menu).indexOf(level)] + "\" index \"" + key + '"') parse_button(next_data, key) next_data.chat_id = id var method = "sendMessage" if (item.method) method = item.method if (next_data.method) { method = next_data.method delete next_data.method } const out = that.send(method, next_data) user.i = key return out; } catch (error) { that.log(error) } } // =========================================== function get_user(data) { const id = data.id const users = that.storage.users if (!users[id]) users[id] = { id: id, i: "_", c: {}, l: "_" } if ("first_name" in data || "last_name" in data) users[id].n = ((data.first_name || "") + " " + (data.last_name || "")).trim() return users[id] } function get_item(level, key) { var key = key.split("$%@-") if (key[1] && level[key[0]].button) { return level[key[0]].button[key[1]] } if (level[key[0]]) return level[key[0]] else return level["_"] } function parse_key(level, key, menu, can = true) { var key = ("" + key).split("$%@-") const first_key = parse_level_key(level, key[0], menu, can) if (key[1] && level[first_key].button) { const last_key = parse_level_key(level[first_key].button, key[1], menu, can) return first_key + "$%@-" + last_key } return first_key } function parse_level_key(level, key, menu, can = true) { if (!key || (key[0] == "_" && can) || !(key in level)) { if ("_" in level) key = "_" else throw Error('BOTMENU: index "_" in list "' + Object.keys(menu)[Object.values(menu).indexOf(level)] + '" is not defined') } if (typeof level[key] == 'string') { return parse_level_key(level, level[key], menu) } return key } function parse_item(level, key, id, input, user, cmdinput, data) { var item = get_item(level, key) if (typeof item == 'function') item = item(id, input, user, cmdinput, data) return item } async function parse_text(id, user, last, input, level, menu, data) { var next = last.next if (typeof next == 'function') { user.c[user.i] = input next = await next(id, input, user, user.i, data) user.c = [] } if (typeof next == 'object') { if (!(input in next)) { if ("_" in next) { next = next._ } else { throw Error('BOTMENU: index "_" of object "next" in index "' + Object.keys(level)[Object.values(level).indexOf(last)] + '" in level "' + Object.keys(menu)[Object.values(menu).indexOf(level)] + '" is not defined') } } else next = next[input] } else if (typeof next == 'string') { user.c[user.i] = input } else if (typeof next == 'undefined') { if (input[0] == "_") input = "_" next = input } return next; } async function parse_data_item(id, item, input, user, cmdinput, data) { if (typeof item.data == 'function') item = await item.data(id, input, user, cmdinput, data) else item = item.data if (typeof item == "string") return { text: item } return item } async function parse_button(item, key) { key = ("" + key).split("$%@-")[0] if (typeof item == "object" && item.reply_markup && item.reply_markup.inline_keyboard) { const buttons = item.reply_markup.inline_keyboard for (const i in buttons) { for (const j in buttons[i]) { const btn = buttons[i][j] if ("callback_data" in btn && !("" + btn.callback_data).includes(spc)) { var buttons_names_i = buttons_names.indexOf(btn.text) if (buttons_names_i == -1) buttons_names_i = buttons_names.push(btn.text) - 1 var buttons_keys_i = buttons_keys.indexOf(key) if (buttons_keys_i == -1) buttons_keys_i = buttons_keys.push(key) - 1 btn.callback_data += spc + buttons_keys_i + spc + buttons_names_i } } } } } function get_user_level(menu, key) { if (key in menu) var level = menu[key] else if ("_" in menu) { var level = menu._ } else throw Error('BOTMENU: level "_" in menu is not defined') if (typeof level == 'string') { return get_user_level(menu, menu[key]) } return level; } function parse_cmd(input) { if (!input.includes(" ")) { var cmd = "_" + input.substring(1) if (cmd == "_start") cmd = "start" return [cmd] } else { var cmd = "_" + input.substring(1, input.indexOf(" ")) if (cmd == "_start") cmd = "start" return [cmd, input.substring(input.indexOf(" ") + 1)] } } module.exports = that