'nodeJS - How to run cron job to send telegram bot messages

I have this code in my telegram bot:

const fs = require('fs/promises');
const keyFile = 'luminous-re1c7.json'
const { Storage } = require('@google-cloud/storage')
const storage = new Storage()
const bucket = storage.bucket('bakekabot-storage')
bucket.file(keyFile).download({ 
    destination: keyFile 
}).then( response => {
    console.log(response)
})

const { Datastore } = require('@google-cloud/datastore');
const datastore = new Datastore({
    projectId: 'lumi13', 
    keyFile: keyFile
});

const cron = require('node-cron');
cron.schedule('* 1 * * * *',  () => {
    console.log('Sending alert to subscribers each minute!TEST MODE ON')
    datastore.get(['bakekabot_subscribers']).then(console.log)
}).start()
//task.start();

const puppeteer = require('puppeteer');
const TelegramBot = require('node-telegram-bot-api');
const bot = new TelegramBot('541070:A', {
    polling: true,
    //  webHook: { 
    //     port: process.env.PORT
    // } 
})

const baseURL = 'https://www.example.com/'

let chatId = Number
let cityList = Array
let urlList = Array
let announces = Array 
let type = String
let city = String
const regex = /[\[\],"]/

fs.readFile('city-list', { encoding: 'utf-8'}).then( (content) => {
    let splittedContent = content.split(regex).filter( el => el.length > 0 )
    cityList = splittedContent.map( el => {
        let cbdata = `{"place":"${el.toLowerCase()}","command":"/place"}` 
        return [{text: el, callback_data: cbdata}]
    })
})

fs.readFile('url-list', { encoding: 'utf-8' }).then( (content) => {
    let splittedContent = content.split(regex).filter( el => el.length > 0 )
    urlList = splittedContent.map( (el) => {
        return el
    })
})

bot.on('polling_error', err => console.log(err) )

/* */
bot.onText(/\/start/, async (message, match) => {    

    chatId = message.chat.id
    await bot.sendMessage(chatId, `Hello ${message.chat.first_name}!What are you looking for?`, {
        protect_content: true,
        parse_mode: 'Markdown',
        reply_markup: {
            inline_keyboard: [
                [{text: 'IC', callback_data: '{"type":"ic","command":"/start"}'}],
                [{text: 'WvM', callback_data: '{"type":"wvm","command":"/start"}'}],
                [{text: 'MvM', callback_data: '{"type":"mvm","command":"/start"}'}],
                [{text: 'C', callback_data: '{"type":"c","command":"/start"}'}]
            ]
        }
    })
})

bot.on('callback_query', (answer) => {
    chatId = answer.message.chat.id
    let data = JSON.parse(answer.data) 
    console.log(data)
    bot.sendChatAction(chatId, 'typing')
    if( data.command === '/start' ){
        type = data.type
        console.log(type)
        bot.sendMessage(chatId, `You selected category ${data.type.split('-').join(' ')}. Available city list below`, {
            protect_content: true
        })
        bot.sendChatAction(chatId, 'typing')
        bot.sendMessage(chatId, `Select a city:`, {
            protect_content: true,
            parse_mode: 'Markdown',
                reply_markup: {
                inline_keyboard: cityList
            }
        })
        bot.answerCallbackQuery(answer.id).then(console.log)   
    }
    if( data.command === '/place' ){
        city = data.place
        console.log(city)
        const searched = urlList.find( el => el.includes( city.toLowerCase() ) )
        const url = new URL(searched)
        const announcesURL = `https://${url.host}/${type}/`

        console.log(searched ,searched.length, announcesURL)

        puppeteer.launch({  
            headless: true, 
            args: [
                '--no-sandbox',
                '--disable-setuid-sandbox'
            ]
        }).then( async (browser) => {
            const page = await browser.newPage()
            const navigationPromise = page.waitForNavigation({
                waitUntil: 'networkidle0'
            })
            await page.goto(announcesURL)

            await page.waitForSelector('.bakecaincontri > #app > .alert > .btn')
            await page.click('.bakecaincontri > #app > .alert > .btn')

            await navigationPromise

            await page.waitForSelector('#lightbox-vm18 > .modal-dialog > .modal-content > .modal-footer > .btn-primary')
            await page.click('#lightbox-vm18 > .modal-dialog > .modal-content > .modal-footer > .btn-primary')
            
            await page.waitForSelector('#app > main > .container > .item-card')
            
            await page.waitForSelector('.item-heading > .item-title > a')
            
            announces = await page.$$eval('.item-heading > .item-title > a', (el) =>  {
                return el.map( (item) => {
                    return {
                        title: item.innerHTML,
                        link: item.getAttribute('href')
                    }
                })
            })
            
            await browser.close()
            let responseMessage = `Available announces for ${city}:\n`;
            announces.forEach( (announce, i) => {
                responseMessage += `${i+1}) <a href="${announce.link}">${announce.title}</a>\n\n`
            })
            await bot.sendMessage(chatId, responseMessage, {
                protect_content: true,
                parse_mode: 'HTML', 
                disable_web_page_preview: true 
            })
            await bot.sendChatAction(chatId, 'typing')
            await bot.sendMessage(chatId, `Do you want an alert for ${city} ${type.split('-').join(' ')}?`, {
                protect_content: true,
                reply_markup: {
                    inline_keyboard: [
                        [{text: 'Yes', callback_data: '{"action":"subscribe","command":"/alert"}'}],
                        [{text: 'No', callback_data: '{"action":"ignore","command":"/alert"}'}]
                    ]
                }
            })
        })
        bot.answerCallbackQuery(answer.id).then(console.log)
    }
    if(data.command === '/alert' && data.action === 'subscribe'){
        let key = datastore.key(['bot_subscribers', `subscriber_${chatId}`])
        let subscriber = {
            key: key,
            data: {
                userID: chatId,
                announces_category: type,
                location: city
            }
        }
        datastore.save(subscriber)
        console.log(`subscriber_${chatId} saved into database!`)
        bot.sendMessage(chatId, 'Alert activated!')
        bot.answerCallbackQuery(answer.id).then(console.log)
    }   
    if(data.command === '/alert' && data.action === 'ignore'){
        console.log('notifiche ignorate')
        bot.answerCallbackQuery(answer.id).then(console.log)
    }
})

I want to setup a cron job that will run daily and that will load from the database all the available subscribers and send them a message. I'm using node-cron but I've noticed that the cron job will run only once also if I've set it for test to run every minute. How I can correctly shedule a daily cron job? Maybe the bot is blocking the cron execution?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source