29.01.2023, 12:09
|
Интересующийся
|
|
Регистрация: 17.08.2017
Сообщений: 19
|
|
Помогите с ассинхронностью в телеграм боте
const mysql = require("mysql2");
require('dotenv').config()
const TelegramApi = require('node-telegram-bot-api')
const bot = new TelegramApi(process.env.BOT_TOKEN, {polling: true})
var mysqlConfig = require('./my_sql_connect.js');
const cron = require("node-cron");
const shellexe = require('./requests/func.js')
const propotkl=5;
bot.setMyCommands([
{command: '/add', description: 'Add node: /add xxx.xxx.xxx.xxx:9000'},
{command: '/delete', description: 'Delete node: /delete xxx.xxx.xxx.xxx:9000'},
{command: '/notif', description: 'show logs'},
{command: '/notifoff', description: 'hide logs'},
{command: '/my', description: 'your nodes'}
])
const start = () => {
bot.on('message', async msg => {
const text = msg.text;
//console.log(msg)
if(text === '/start'){
return bot.sendMessage(msg.from.id, `Welcome!`)
}
if(text === '/my'){
console.log("нажат my")
bot.sendMessage(msg.from.id,`Ваши ip: skljfkdsl`)
return
}
return bot.sendMessage(msg.from.id, `Unknown command`)
})
}
start()
var pool=mysql.createPool(mysqlConfig);
cron.schedule('* */1 * * * *', async () => {
let bddata;
pool.getConnection(function(err,connection){
if (err) {
connection.release();
console.log("ошибка соед");
//bot.sendMessage(msg.from.id,'нет соединения с БД')
reject(err)
}else{
console.log("зашли читать БД");
const sql = `SELECT * FROM userip`;
pool.query(sql, '',function(err, resp) {
if(err) {
//bot.sendMessage(msg.from.id,'не удалось добавить данные')
return console.log(err);
}
bddata =resp
console.log("resp")
if(bddata && bddata!=''){
bddata.map((val)=>{
console.log(val)
console.log("curl:")
const p = new Promise(function(resolve, reject){
//let main = await shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
let tmp = shellexe(`curl --max-time 3 --location --silent --request POST http://${val.ipu} --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
resolve(tmp)
})
p.then(data=>{
console.log(data)
})
})
//let curlres = proverka();
console.log("curl res:")
//console.log(curlres)
111111
}else{
console.log(`База пуста`)
}
connection.release(); // закрываем соединение с базой данных
})
}
});
console.log("bddata")
})
Привет! Набросал скрипт для бота и не могу разобраться с асинхронностью.
start() - это функция от бота. Прием команд от пользователя через телегу. Например /my вытаскивает все заведенные ip.
И есть второй раздел с кроном. Который мониторит. Надо чтобы второй раздел с кроном работал как бы независимо от первого. В переменную bddata загружаются сотни ip адресов. Программа вытаскивает айпи и через курл проверяет доступность. 1 адрес через курл занимает 3 секунды. Если адресов много, то это будет долго.
И дело в том, что когда вызываю /my в start, то ответ приходит только после окончания проверки всех ip из базы. Как сделать, чтобы функции в start не зависели от тормоззов функции с курлом?
Т.е. нужно, чтобы при нажатии /my сразу пришел ответ не дождавшись выполнения функции в крон
Последний раз редактировалось tarabukinivan, 29.01.2023 в 15:15.
|
|
30.01.2023, 09:32
|
Интересующийся
|
|
Регистрация: 17.08.2017
Сообщений: 19
|
|
Сообщение от tarabukinivan
|
const mysql = require("mysql2");
require('dotenv').config()
const TelegramApi = require('node-telegram-bot-api')
const bot = new TelegramApi(process.env.BOT_TOKEN, {polling: true})
var mysqlConfig = require('./my_sql_connect.js');
const cron = require("node-cron");
const shellexe = require('./requests/func.js')
const propotkl=5;
bot.setMyCommands([
{command: '/add', description: 'Add node: /add xxx.xxx.xxx.xxx:9000'},
{command: '/delete', description: 'Delete node: /delete xxx.xxx.xxx.xxx:9000'},
{command: '/notif', description: 'show logs'},
{command: '/notifoff', description: 'hide logs'},
{command: '/my', description: 'your nodes'}
])
const start = () => {
bot.on('message', async msg => {
const text = msg.text;
//console.log(msg)
if(text === '/start'){
return bot.sendMessage(msg.from.id, `Welcome!`)
}
if(text === '/my'){
console.log("нажат my")
bot.sendMessage(msg.from.id,`Ваши ip: skljfkdsl`)
return
}
return bot.sendMessage(msg.from.id, `Unknown command`)
})
}
start()
var pool=mysql.createPool(mysqlConfig);
cron.schedule('* */1 * * * *', async () => {
let bddata;
pool.getConnection(function(err,connection){
if (err) {
connection.release();
console.log("ошибка соед");
//bot.sendMessage(msg.from.id,'нет соединения с БД')
reject(err)
}else{
console.log("зашли читать БД");
const sql = `SELECT * FROM userip`;
pool.query(sql, '',function(err, resp) {
if(err) {
//bot.sendMessage(msg.from.id,'не удалось добавить данные')
return console.log(err);
}
bddata =resp
console.log("resp")
if(bddata && bddata!=''){
bddata.map((val)=>{
console.log(val)
console.log("curl:")
const p = new Promise(function(resolve, reject){
//let main = await shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
let tmp = shellexe(`curl --max-time 3 --location --silent --request POST http://${val.ipu} --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
resolve(tmp)
})
p.then(data=>{
console.log(data)
})
})
//let curlres = proverka();
console.log("curl res:")
//console.log(curlres)
111111
}else{
console.log(`База пуста`)
}
connection.release(); // закрываем соединение с базой данных
})
}
});
console.log("bddata")
})
Привет! Набросал скрипт для бота и не могу разобраться с асинхронностью.
start() - это функция от бота. Прием команд от пользователя через телегу. Например /my вытаскивает все заведенные ip.
И есть второй раздел с кроном. Который мониторит. Надо чтобы второй раздел с кроном работал как бы независимо от первого. В переменную bddata загружаются сотни ip адресов. Программа вытаскивает айпи и через курл проверяет доступность. 1 адрес через курл занимает 3 секунды. Если адресов много, то это будет долго.
И дело в том, что когда вызываю /my в start, то ответ приходит только после окончания проверки всех ip из базы. Как сделать, чтобы функции в start не зависели от тормоззов функции с курлом?
Т.е. нужно, чтобы при нажатии /my сразу пришел ответ не дождавшись выполнения функции в крон
|
Пробовал весь цикл обернуть промисом:
bddata =resp
console.log("resp")
if(bddata && bddata!=''){
const p = new Promise(function(resolve, reject){
console.log("начало цикла")
bddata.map((val)=>{
//let main = await shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
shellexe(`curl --max-time 3 --location --silent --request POST http://${val.ipu} --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
})
console.log("конец цикла")
resolve(tmp)
})
p.then(data=>{
console.log(data)
})
//let curlres = proverka();
console.log("curl res:")
//console.log(curlres)
111111
}else{
console.log(`База пуста`)
}
connection.release();
и даже так:
bddata =resp
console.log("resp")
const p = new Promise(function(resolve, reject){
if(bddata && bddata!=''){
console.log("начало цикла")
bddata.map((val)=>{
//let main = await shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
shellexe(`curl --max-time 3 --location --silent --request POST http://${val.ipu} --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
})
console.log("конец цикла")
resolve(tmp)
//let curlres = proverka();
//console.log(curlres)
111111
}else{
console.log(`База пуста`)
}
})
p.then(data=>{
console.log(data)
})
connection.release(); // закрываем соединение с базой данных
})
Все равно ждет конец цикла, парсит все курл, только потом идет выполнять /my
|
|
30.01.2023, 12:34
|
|
Профессор
|
|
Регистрация: 03.02.2020
Сообщений: 2,750
|
|
Ничего не понимаю в ботах, для телеги, но смущает ваш map.
Сам map должен возвращать массив.
Функция, которая внутри map должна возвращать элемент массива.
У вас этого ничего нет.
Что такое tmp в resolve(tmp) тоже не известно.
bdata это что? строка? (есть проверка bddata!='')
|
|
30.01.2023, 14:09
|
Интересующийся
|
|
Регистрация: 17.08.2017
Сообщений: 19
|
|
Сообщение от voraa
|
Ничего не понимаю в ботах, для телеги, но смущает ваш map.
Сам map должен возвращать массив.
Функция, которая внутри map должна возвращать элемент массива.
У вас этого ничего нет.
Что такое tmp в resolve(tmp) тоже не известно.
bdata это что? строка? (есть проверка bddata!='')
|
bdata - массив объектов. Это я просто для теста редактировал. Пусть будет так
if(bddata && bddata!=''){
console.log("начало цикла")
bddata.map((val)=>{
let main = shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
//let res = shellexe(`curl --max-time 3 --location --silent --request POST http://${val.ipu} --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
console.log(main)
})
resolve(1)
//let curlres = proverka();
//console.log(curlres)
111111
}else{
console.log(`База пуста`)
}
Там дело не в том, что возвращает map.
Map правильно перебирает объекты val типа:
+-----+-----------+---------------------+----------+--------+
| id | userid | ipu | propuski | worked |
+-----+-----------+---------------------+----------+--------+
| 166 | 416844240 | 109.237.85.201:9000 | 4 | 1 |
| 167 | 416844240 | 109.237.85.202:9000 | 3 | 1 |
| 168 | 416844240 | 109.237.85.203:9000 | 2 | 1 |
| 169 | 416844240 | 109.237.85.204:9000 | 0 | 1 |
| 170 | 416844240 | 109.237.85.205:9000 | 0 | 1 |
| 171 | 416844240 | 109.237.85.206:9000 | 0 | 1 |
| 172 | 416844240 | 109.237.85.207:9000 | 0 | 1 |
| 173 | 416844240 | 109.237.85.207:9000 | 0 | 1 |
И получает ответ, доступен нода или нет
Здесь я хочу, чтобы когда вызываю фукцию start, чтобы она моментально отвечала, а не дожидалась прохода map.
Последний раз редактировалось tarabukinivan, 30.01.2023 в 14:17.
|
|
30.01.2023, 14:10
|
Интересующийся
|
|
Регистрация: 17.08.2017
Сообщений: 19
|
|
Т.е. Хочу, чтобы поток был свободен и отвечал на start во время прохода по массиву объектов. И возвращался толко когда закончит проход.
Короче когда начимаю start она не отвечает. Ждет когда переберет весь массив, только потом дает ответ start
Последний раз редактировалось tarabukinivan, 30.01.2023 в 14:13.
|
|
30.01.2023, 15:00
|
Интересующийся
|
|
Регистрация: 17.08.2017
Сообщений: 19
|
|
Пусть код будет так:
Код:
|
const mysql = require("mysql2");
require('dotenv').config()
const TelegramApi = require('node-telegram-bot-api')
const bot = new TelegramApi(process.env.BOT_TOKEN, {polling: true})
var mysqlConfig = require('./my_sql_connect.js');
const cron = require("node-cron");
const shellexe = require('./requests/func.js')
const propotkl=5;
bot.setMyCommands([
{command: '/add', description: 'Add node: /add xxx.xxx.xxx.xxx:9000'},
{command: '/delete', description: 'Delete node: /delete xxx.xxx.xxx.xxx:9000'},
{command: '/notif', description: 'show logs'},
{command: '/notifoff', description: 'hide logs'},
{command: '/my', description: 'your nodes'}
])
const start = () => {
bot.on('message', async msg => {
const text = msg.text;
//console.log(msg)
if(text === '/start'){
return bot.sendMessage(msg.from.id, `Welcome!`)
}
if(text === '/my'){
console.log("нажат my")
bot.sendMessage(msg.from.id,`Ваши ip: skljfkdsl`)
return
}
return bot.sendMessage(msg.from.id, `Unknown command`)
})
}
start()
//var pool=mysql.createPool(mysqlConfig);
cron.schedule('* */1 * * * *', async () => {
const p = new Promise(function(resolve, reject){
let main =[]
for(var i = 0; i < 7;i++){
main.push(shellexe(`curl --max-time 3 --location --silent --request POST https://fullnode.testnet.sui.io:443 --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`))
}
resolve(main)
})
p.then(data =>{
console.log(data)
})
}) |
Мне нужно как-то for обернуть в промис, чтобы /my отвечал моментально. В таком виде при вызове /my в start ответ приходит не сразу. Отвечат только когда for завершится.
|
|
30.01.2023, 17:51
|
|
Профессор
|
|
Регистрация: 03.02.2020
Сообщений: 2,750
|
|
А что shellexe возвращает? Promis?
|
|
31.01.2023, 02:38
|
Интересующийся
|
|
Регистрация: 17.08.2017
Сообщений: 19
|
|
Сообщение от voraa
|
А что shellexe возвращает? Promis?
|
Да в нем https://www.npmjs.com/package/shelljs
она выполняет курл и получает ответ
|
|
31.01.2023, 07:25
|
|
Профессор
|
|
Регистрация: 03.02.2020
Сообщений: 2,750
|
|
Тогда надо что то вроде этого
const arp = bbdata.map (val => {
return shellexe(`.....`);
})
// Ждем когда все закончатся
Promise.all(arp).then(data => {....}) // data массив
или
const arp = bbdata.map (val => {
return shellexe(`.....`);
})
// обрабатываем по мере исполнения
for await (data of arp) {
....
}
Последний раз редактировалось voraa, 31.01.2023 в 07:30.
|
|
31.01.2023, 10:59
|
Интересующийся
|
|
Регистрация: 17.08.2017
Сообщений: 19
|
|
Сообщение от voraa
|
Тогда надо что то вроде этого
const arp = bbdata.map (val => {
return shellexe(`.....`);
})
// Ждем когда все закончатся
Promise.all(arp).then(data => {....}) // data массив
или
const arp = bbdata.map (val => {
return shellexe(`.....`);
})
// обрабатываем по мере исполнения
for await (data of arp) {
....
}
|
Извините не очень понял как применить ваш код, но вроде так?:
if(bddata && bddata!=''){
const arp = bddata.map (val => {
return shellexe(`curl --max-time 3 --location --silent --request POST [url]https://fullnode.testnet.sui.io:443[/url] --header 'Content-Type: application/json' --data-raw '{ "jsonrpc":"2.0", "method":"sui_getTotalTransactionNumber","id":1}' 2>&1`)
})
async function getData() {
for await (data of arp) {
console.log(data)
}
}
getData()
}else{
console.log(`База пуста`)
}
В таком ввиде все равно /my выполняется только после полного прохода по map. Я неправильно написал?
|
|
|
|