1
0
This repository has been archived on 2022-11-26. You can view files and clone it, but cannot push or open issues or pull requests.

594 lines
16 KiB
JavaScript
Raw Permalink Normal View History

const DEF_DELAY = 1000;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms || DEF_DELAY));
}
var config = require('./config');
var Bot = require('node-telegram-bot-api');
var bot = new Bot(process.env.TOKEN||config.token, { polling: true });
console.log('Бот был запущен');
const Courier = require('./curier_api');
var users = {};
bot.onText(/^/, function (msg) {
var id = msg.chat.id;
const args = msg.text.slice("/").trim().split(/ +/g);
const command = args.shift().toLowerCase();
var text = args.join(" ");
start_answering(id,command,text);
});
//Запуск нужной функции
async function launchFunctionByName(data){
switch(data.name){
case 'login':
var answer = await command_login(data);
return answer;
break;
case 'relogin':
var answer = await command_relogin(data);
return answer;
break;
case 'relogin_all':
var answer = await command_relogin_all(data);
return answer;
break;
case 'logout':
var answer = await command_logout(data);
return answer;
break;
case 'help':
var answer = await command_help(data);
return answer;
break;
case 'myslots':
var answer = await command_myslots(data);
return answer;
break;
case 'freeslots':
var answer = await command_freeslots(data);
return answer;
break;
case 'orders':
var answer = await command_orders(data);
return answer;
break;
case 'query':
var answer = await command_query(data);
return answer;
break;
case 'reload_bd':
var answer = await command_reload_bd(data);
return answer;
break;
case 'search_point':
var answer = await command_search_point(data);
return answer;
break;
case 'test':
var answer = await command_test(data);
return answer;
break;
case 'newfreeslots':
var answer = await command_newfreeslots(data);
return answer;
break;
default:
return data.answer;
break;
}
}
//Выполнить операцию с таблицей
async function command_query(data){
var answer = data.answer;
var client = await new Client({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
})
await client.connect()
.catch(e => {
console.error(e);
})
try {
var client_answer = await client.query(data.text);
//delete client_answer["builtins"];
delete client_answer["_types"];
delete client_answer["fields"];
delete client_answer["_parsers"];
delete client_answer["RowCtor"];
delete client_answer["rowAsArray"];
delete client_answer["oid"];
answer += JSON.stringify(client_answer).replace(/{/g,'{\n').replace(/}/g,'\n}').replace(/,/g,',\n')
await client.end();
}
catch(e){
console.error(e);
await client.end();
answer += 'Ошибка запроса'
};
return answer;
}
//Получить список всех доступных комманд
function command_help(data){
var answer = data.answer;
config.commands.forEach(function (values,keys) {
if(values.have_description)
if((values.need_admin==data.is_Admin)||(!values.need_admin))
if((values.need_auth==data.is_Auth)||(values.show_after_login&&data.is_Auth))
answer += `\n ${keys} - ${values.description}`;
});
if(data.is_Admin){
answer += `\n----------------------
<b>Команды администратора:</b>`;
config.admin_commands.forEach(function (values,keys) {
if(values.have_description)
if((values.need_auth==data.is_Auth)||(values.show_after_login&&data.is_Auth))
answer += `\n ${keys} - ${values.description}`;
});
}
return answer;
}
//Авторизоваться
async function command_login(data){
var answer = data.answer;
var dannie = data.text.split("-")
if(dannie.length == 2){
var new_user_data = {
id: data.id,
username: dannie[0].trim(),
password: dannie[1].trim()
}
var new_user = users[data.id];
if(!new_user) new_user = new Courier(new_user_data);
else new_user.updateUser(new_user_data);
if(await new_user.auth()&&await new_user.getInfo()){
answer = `<b>Вход выполнен успешно</b>
Авторизован: ${new_user.info.name}
`;
var zones = await new_user.getMyZones();
answer += `Зоны работы: `;
for(var zone in zones) answer += `<code>${zone}</code>; `
answer += `\n\n<i>Для изменений отслеживаемой зоны работы используйте</i> /setzone`;
}
else
answer = 'Возникла ошибка при авторизации';
users[data.id] = new_user;
newUsers.push(new_user.data());
console.log('Авторизован пользователь id=' + data.id)
}
return answer;
}
//Список запланнированных слотов
async function command_relogin(data){
var answer = data.answer;
if(await users[data.id].auth()&&await users[data.id].getInfo()){
answer += `Авторизован: ${users[data.id].info.name}`;
}
else
answer = `Возникла ошибка :(
Авторизуйтесь заново с помощью команды /login`;
update_users.push(data.id);
return answer;
}
//Обновить для всех авторизацию
async function command_relogin_all(data){
var answer = data.answer;
for await(var id of Object.keys(users)){
if(!await users[id].getInfo()){
if(await users[id].auth()&&await users[id].getInfo()){
answer += `Авторизован: ${users[id].info.name}`;
update_users.push(id);
}
else
answer += `Не авторизован: ${users[id].username}`;
answer += `\n`
}
}
if(answer == `<b>Переавторизация</b>\n`) answer = `Все пользователи авторизованы`
return answer;
}
//Список запланнированных слотов
async function command_logout(data){
await users[data.id].reset();
await update_users.push(data.id);
return data.answer;
}
//Список запланнированных слотов
async function command_myslots(data){
return await users[data.id].getPlanned();
}
//Список свободных слотов
async function command_freeslots(data){
return await users[data.id].getFreeSlotsWeek();
}
//Текущий заказ
async function command_orders(data){
return await users[data.id].getOrdersText();
}
//Список новых слотов
async function command_newfreeslots(data){
users[data.id].is_waiting = false;
return await users[data.id].getNewFreeSlotsWeek();
}
//Перезапуск бд
async function command_reload_bd(data){
await init_database()
return data.answer;
}
const fuzzysearch = require('fuzzysearch');
const levenshtein = require('js-levenshtein');
//Поиск нужной лавки
async function command_search_point(data){
var answer;
if(data.text.length==0) return `Для использования команды введите название лавки после /setzone
Например: /setzone Ветеранов`;
var names = [];
for(var zone_name in config.points){
if(data.text.toLowerCase().split(' ').join('') == zone_name.toLowerCase().split(' ').join('')) {
names = [zone_name];
break;
}
else if(fuzzysearch(data.text.toLowerCase().split(' ').join(''), zone_name.toLowerCase().split(' ').join(''))){
names.push(zone_name)
}
}
if(names.length == 1) {
answer = `<b>Выбрана точка:</b> ${names}(${config.points[names]})`
users[data.id].clearZones();
users[data.id].addZone(config.points[names]);
await update_users.push(data.id);
// console.log(users[data.id]);
}
else if(names.length == 0){
var minimal = 100;
for(var zone_name in config.points){
var a = levenshtein(data.text.toLowerCase().split(' ').join(''), zone_name.toLowerCase().split(' ').join(''));
if(a<minimal) {
answer = zone_name;
minimal = a;
}
}
var answer = `По вашему запросу ничего не найдено...
Возможно вы имели ввиду <code>${answer}</code>`;
} else if(answer == '') answer = 'Не найдено сопадений'
else {
answer = `<b>Найденные лавки:</b>
`;
for(var name of names){
answer+=`<code>${name}</code>\n`
}
}
return answer;
}
//Тестовая команда
async function command_test(data){
var answer = data.answer;
//console.log('Выбрана точка работы: ', await users[data.id].getMainZone());
return answer;
}
//Выбрать канал ответов для сообщения
function start_answering(id,command,text){
if(!users[id])
users[id] = new Courier({id:id});
if(!users[id].is_waiting){
var command_info = config.commands.get(command)||config.admin_commands.get(command);
if(!command_info) {
bot.sendMessage( id, config.defaulttext.unknown_command);
}
else {
if(command_info.need_api)
messages_wait_Yandex.push({
id : id,
text : text,
command_info : command_info
});
else
messages.push({
id : id,
text : text,
command_info : command_info
});
}
}
else bot.sendMessage( id, config.defaulttext.need_wait);
}
setTimeout(() => setInterval(() => start_answering(247608317,'/newfreeslots'), 20000), 5000);
//Ответ на сообщения не требующие API яндекса
messages = [];
answer_for_messages();
async function answer_for_messages(){
var message = messages.shift();
while (message) {
var id = message.id;
var command_info = message.command_info;
var answer = "";
var buttons = [];
var user_is_admin = (users[id].mode > 1);
if(command_info.need_admin&&!user_is_admin)
answer = config.defaulttext.need_admin;
else {
var user_is_auth = users[id].checkAuth();
if(command_info.need_auth&&!user_is_auth) {
answer = config.defaulttext.need_auth;
// buttons = getButtonsByNames(config.defaulttext.need_auth.buttons,id);
}
else {
answer = command_info.answer || 'no_answer';
// buttons = getButtonsByNames(command_info.buttons,id);
if(command_info.function_name){
var data = {
name : command_info.function_name,
id : id,
is_Auth : user_is_auth,
is_Admin : user_is_admin,
answer : answer,
text : message.text
}
try {
users[id].is_waiting = true;
answer = await launchFunctionByName(data);
} catch (e) {
console.log(e);
answer = 'Возникла ошибка';
users[id].is_waiting = false;
}
}
}
}
message = messages.shift();
users[id].is_waiting = false;
if(answer != 'no_answer'){
if (answer.length >= 4000)
while(answer.length>0){
await bot.sendMessage( id, answer.substring(0,4000), {
parse_mode: 'HTML',
reply_markup: {
inline_keyboard: buttons
}
});
answer = answer.substring(4000);
}
else
bot.sendMessage( id, answer, {
parse_mode: 'HTML',
reply_markup: {
inline_keyboard: buttons
}
});
}
}
setTimeout(answer_for_messages, 100);
}
var yandex_api = [1,1,1,1,1,1,1,1];
messages_wait_Yandex = [];
messages_with_Yandex = [];
add_messages_with_Yandex()
answer_for_messages_with_Yandex()
async function add_messages_with_Yandex(){
while((messages_wait_Yandex.length > 0) && (yandex_api.length > 0)){
var message = messages_wait_Yandex.shift();
var options = yandex_api.shift();
//console.log(options);
await messages_with_Yandex.push(message);
}
setTimeout(add_messages_with_Yandex, 100);
}
async function answer_for_messages_with_Yandex(){
var message = messages_with_Yandex.shift();
while (message) {
var id = message.id;
var command_info = message.command_info;
var answer = "";
var buttons = [];
var user_is_admin = (users[id].mode > 1);
if(command_info.need_admin&&!user_is_admin)
answer = config.defaulttext.need_admin;
else {
var user_is_auth = users[id].checkAuth();
if(command_info.need_auth&&!user_is_auth) {
answer = config.defaulttext.need_auth;
// buttons = getButtonsByNames(config.defaulttext.need_auth.buttons,id);
}
else {
answer = command_info.answer || 'no_answer';
// buttons = getButtonsByNames(command_info.buttons,id);
if(command_info.function_name){
var data = {
name : command_info.function_name,
id : id,
is_Auth : user_is_auth,
is_Admin : user_is_admin,
answer : answer,
text : message.text
}
try {
users[id].is_waiting = true;
answer = await launchFunctionByName(data);
} catch (e) {
console.log(e);
answer = 'Возникла ошибка';
users[id].is_waiting = false;
}
}
}
}
message = messages_with_Yandex.shift();
yandex_api.push(1);
users[id].is_waiting = false;
if(answer != 'no_answer'){
if (answer.length >= 4000)
while(answer.length>0){
await bot.sendMessage( id, answer.substring(0,4000), {
parse_mode: 'HTML',
reply_markup: {
inline_keyboard: buttons
}
});
answer = answer.substring(4000);
}
else
bot.sendMessage( id, answer, {
parse_mode: 'HTML',
reply_markup: {
inline_keyboard: buttons
}
});
}
}
setTimeout(answer_for_messages_with_Yandex, 100);
}
/******************--- databaseConnect ----**************************/
const { Client } = require('pg');
const client = new Client({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
})
client.connect()
.catch(e => {
console.error(e);
})
.then(()=>{init_database()});
var bd_loaded = false;
function init_database(){
(async () => {
var create_table = `CREATE TABLE IF NOT EXISTS USERS(
ID INT PRIMARY KEY NOT NULL,
TOKEN VARCHAR(1000) NOT NULL DEFAULT 'unauthorized',
USERNAME VARCHAR(45) NOT NULL DEFAULT 'no_username',
PASSWORD VARCHAR(20) NOT NULL DEFAULT 'no_password',
MODE INT NOT NULL DEFAULT 0,
ZONES TEXT NOT NULL DEFAULT 'no_zones'
);`;
await client.query(create_table)
var load_users = `SELECT * FROM USERS;`;
await client.query(load_users, async (err,res) => {
var users_ = res.rows;
var auth_needed = 0;
for await(var user of users_) {
if(user.zones === 'no_zones') user.zones = '';
user.zones = user.zones.split(',')
users[user.id] = new Courier(user);
if(!(await users[user.id].getInfo()))
auth_needed++;
}/*var i=0; i<users_.length;i++) {
var user_data = {
id: users_[i].id,
username: users_[i].username,
password: users_[i].password,
token: users_[i].token,
mode: users_[i].mode,
zones: users_[i].zones.split(',')
}
users[user_data.id] = new Courier(user_data);
if(!(await users[user_data.id].getInfo()))
auth_needed++;
}*/
console.log(`Из базы данных загружено пользователей: ${users_.length}, нужна повторная авторизация: ${auth_needed}`)
if(!bd_loaded){
setTimeout(saveNewUsers, 5000);
bd_loaded = false;
}
})
})()
.catch(e => {
console.error(e);
setTimeout(init_database, 5000);
});
}
/******************--- databaseConnect ----**************************/
var update_users = [];
const updateUsersClient = new Client({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
});
updateUsersClient.connect();
setTimeout(updateUsersOnServer, 5000);
async function updateUsersOnServer(){
(async () => {
var id = update_users.shift();
while(id){
let update = `UPDATE USERS SET TOKEN = '${users[id].token}', USERNAME = '${users[id].username}', PASSWORD = '${users[id].password}', MODE = ${users[id].mode}, ZONES = '${users[id].zones.join(",")}' WHERE ID = ${id};`
await updateUsersClient.query(update)
id = update_users.shift();
}
setTimeout(updateUsersOnServer, 5000);
})()
.catch(e => {
console.error(e);
setTimeout(updateUsersOnServer, 5000);
});
}
var newUsers = [];
function saveNewUsers(){
(async () => {
var user = newUsers.shift();
while (user){
var add_user = `INSERT INTO USERS(ID, TOKEN, USERNAME, PASSWORD, MODE, ZONES) VALUES(${user.id}, '${user.token}', '${user.username}', '${user.password}', ${user.mode}, '${user.zones.join(",")}') ON CONFLICT (ID) DO UPDATE SET TOKEN = EXCLUDED.TOKEN, USERNAME = EXCLUDED.USERNAME, PASSWORD = EXCLUDED.PASSWORD;`;
//console.log('save ',user)
await client.query(add_user);
user = newUsers.shift();
}
setTimeout(saveNewUsers, 5000);
})()
.catch(e => {
console.error(e);
});
}