Rewrite my BotService class so it schedules jobs and runs generateScreenshot, show only the relevant parts of my code

This is a JSON object with an example of an array of jobs.

[{caption: 'Buen día ${hoy} \n _Lugares disponibles:_ bit.ly/3civct4', report: 'capacidades', chatId: ['5217221530884-1442235787@g.us','5217224584227-1436726497@g.us']}, {caption: 'Buenos días, les comparto su última asistencia registrada.', report: 'asistencia', chatId: ['5217223784886-1598620689@g.us','5217224748923-1440559046@g.us','5217221530884-1423926397@g.us']}, {caption: '!eventos', report: 'eventos', chatId: ['5217223784886-1598620689@g.us','5217221508888-1431783389@g.us','5217224748923-1440559046@g.us','5217221530884-1423926397@g.us','120363026399428220@g.us']}, {caption: '!acuerdos', report: 'acuerdos-cover', chatId: ['5217223784886-1598620689@g.us']}, {caption: 'Buenos días, les comparto estadísticos Covid a nivel Nacional;\n Confirmados:', report: 'covid/A', chatId: ['5217222527199-1546534573@g.us']}, {caption: 'Defunciones en los últimos 12 días ', report: 'covid/B', chatId: ['5217222527199-1546534573@g.us']}]

## App\Services\BotService\index.ts

import {
   LocalAuth,
   Client,
   WAState,
   ClientInfo,
   MessageMedia
}
from "whatsapp-web.js";
import fetch from "node-fetch";
import fs from "fs";
import util from 'util';
import qrcode from "qrcode-terminal";
import actions from "App/Services/ActionsService"
import {
   scheduleJob
} from 'node-schedule';
import {
   Cluster
} from 'puppeteer-cluster';
import xml2js from 'xml2js';
var parser = new xml2js.Parser();
import * as mysql from "mysql";
import moment from 'moment'
import {
   createCanvas,
   loadImage
} from 'canvas';
import tmp from 'tmp';

const readFile = util.promisify(fs.readFile);
const writeFile = util.promisify(fs.writeFile);

export default class BotService {
   public client: Client;
   public qr: string | null = null;
   public state: WAState = WAState.UNPAIRED;
   public ms = 0;
   public lastTitle = "";
   public parser: parser;
   public initialized(ms) {
      this.client.sendMessage(
         "5217291065569@c.us",
         "_🐺 🤖 Cliente listo después de " + ms + " milisegundos!_ "
      );
   }
   async function generateScreenshot(jobs) {
      // Create a new puppeteer cluster with 2 workers.
      const cluster = await Cluster.launch({
         concurrency: Cluster.CONCURRENCY_CONTEXT,
         maxConcurrency: 2,
      });

      // Define a task that each worker will run to generate a screenshot.
      cluster.task(async ({
         page,
         data: job
      }) => {
         // Set the viewport and user agent (just in case).
         await page.setViewport({
            width: 1280,
            height: 800
         });
         await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36');

         const url = 'https://reportes.casitaapps.com/' + job.report;

         // Navigate to the URL specified in the job object and wait for it to load.
         await page.goto(url);

         // Wait for the page to indicate that it is ready.
         const watchDog = page.waitForFunction('window.status === "ready"');
         await watchDog;

         // Take a screenshot of the element with the specified selector and return it as a buffer.
         const element = await page.$('#frame');
         const screenshot = await element.screenshot();
         return screenshot;
      });

      // Generate a screenshot for each job in the array.
      const promises = jobs.map((job) => cluster.execute(job));
      const screenshotData = await Promise.all(promises);

      // Close the cluster when all jobs are finished.
      await cluster.close();

      return screenshotData;
   }
   public async delay(): Promise < void > {
      const min = Math.ceil(3000);
      const max = Math.floor(10000);
      const ms = Math.floor(Math.random() * (max - min)) + min;
      await new Promise((resolve) => setTimeout(resolve, ms));
   }
   constructor() {
      const authStrategy: LocalAuth = new LocalAuth({
         clientId: "client-one",
         dataPath: "C:/Server/htdocs/Adonis/whatsapp/.wwebjs_auth/",
      });
      this.actions = new actions();
      this.client = new Client({
         puppeteer: {
            headless: false,
            executablePath: 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe'
         },
         takeoverOnConflict: true,
         takeoverTimeoutMs: 10,
         authStrategy,
      });
      this._listenForReady();
      this._listenIncoming();
      this._listenForQRCode();
      this._listenForChangeState();

      this._initializeClient()
         .then(async () => {
            const version = await this.client.getWWebVersion();
            console.log(`WHATSAPP WEB VERSION: v${version}`);
            this.state = WAState.CONNECTED;
            const {
               default: EvaService
            } = await import('@ioc:App/Services/EvaService')
            this.actions.eva = EvaService;


         })
         .catch((err) => {
            console.log(err);
         });
   }
   protected async _initializeClient(): Promise < void > {
      return this.client.initialize();
   }
   protected _listenForQRCode(): void {
      this.client.on("qr", (qr: string) => {
         console.log("QR RECEIVED", qr);
         this.qr = qr;
         qrcode.generate(qr, {
            small: true
         });
      });
   }
   protected _listenForReady(): void {
      this.client.on("ready", () => {
         console.log("Client is ready!", "Checking SSN...");
         this._checkSSN();
         // this._clearMysql();
         this._checkScheduled();
         this.state = WAState.CONNECTED;


      });
   }
   protected _listenIncoming(): void {
      this.client.on("message", async (message) => {
         if (message.id.fromMe) return false;
         try {
            this.actions.response(message, this.client);
         } catch (err) {
            console.log('An error occurrsed in the responses logic', err);
         }

      });
      this.client.on("message_create", async (message) => {
         if (!message.id.fromMe) return false;
         try {
            this.actions.response(message, this.client);
         } catch (err) {
            console.log('An error occurrsed in the responses logic', err);
         }

      });
   }
   protected _listenForChangeState(): void {
      this.client.on("change_state", (state: WAState) => {
         console.log("State changed: ");
         this.state = state;
      });
   }
   protected _clearMysql(): void {
      // setInterval(async () => {
      const db = mysql.createConnection({
         host: "localhost",
         user: "root",
         password: "Nicole10*",
         database: 'control_coordinaciones'
      });
      var data = [];
      const promise = new Promise((resolve, reject) => {
         db.query("SELECT CONCAT('KILL ',id,';') as query FROM information_schema.processlist WHERE command='Sleep' AND time > 900;")
            .on("error", (err) => {
               console.error(err);

               reject(err);
            })
            .on("result", (row) => {
               db.pause();

               data.push(row.query);

               db.resume();
            })
            .on("end", () => {
               resolve(data);
            });
      });
      promise.then((data) => {
         //now execute each result as a query and close mysql connection after all queries have been executed.
         const promise2 = new Promise((resolve, reject) => {
            const killQueries = data.map((killQuery) => {
               return new Promise((resolve, reject) => {
                  db.query(killQuery, (err, result) => {
                     if (err) {
                        reject(err);
                     } else {
                        resolve(result);
                     }
                  });
               });
            });
            Promise.all(killQueries).then(() => {
               db.end();
               resolve();
            }).catch((err) => {
               db.end();
               reject(err);
            });
         });
         promise2.then(() => {
            // console.log("All queries executed successfully");
         }).catch((err) => {
            console.error(err);
         });
      }).catch((err) => {
         console.error(err);
      });
      // }, 60000);
   }
   protected _checkScheduled(): void {
      setInterval(async () => {
         var db = mysql.createConnection({
            host: "localhost",
            user: "root",
            password: "Nicole10*",
            database: 'casitaiedis',
            charset: 'utf8mb4'
         });
         var data = [];
         const promise = new Promise((resolve, reject) => {
            db.query("SELECT id, message, scheduled_at, target_id FROM scheduled_messages WHERE scheduled_at <= NOW() AND scheduled_at >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) AND sent = 0")
               .on("error", (err) => {
                  console.error(err);
                  reject(err);
               })
               .on("result", (row) => {
                  db.pause();
                  data.push(row);
                  db.resume();
               })
               .on("end", () => {
                  resolve(data);
               });
         });
         promise.then((data) => {
            if (data.length > 0) {
               for (var i = 0; i < data.length; i++) {
                  this.client.sendMessage(
                     data[i]['target_id'],
                     data[i].message
                  );
                  db.query(`UPDATE scheduled_messages SET sent = '1' WHERE id = '${data[i].id}'`).on("error", (err) => {
                     console.error(err);
                  })
                  db.end();
                  this._postal();
                  // this._clearMysql();
               }
            } else {
               db.end();
               this._postal();
               // this._clearMysql();
               console.log(moment().format('HH:mm:ss'), WAState.CONNECTED);
            }
         });
      }, 50000);
   }
   protected _checkSSN(): void {
      setInterval(async () => {
         var body = await fetch('http://www.ssn.unam.mx/rss/ultimos-sismos.xml').then(res => res.text());
         var xml = await parser.parseStringPromise(body);
         var items = xml.rss.channel[0].item;
         var title = items[0].title[0].trim();
         // var scale = title.split(",")[0]; haz una función por cada grado, un emoji adicional 🚨
         // var tipo = parseFloat(scale) > 5 ? "sismo" : "replica";        
         if (items.length == 1) { //Everyone else
            console.log('ssn', this.lastTitle);
            var mgntd = parseFloat(title.split(",")[0].replace("Preliminar: M ", ""));
            if (title !== this.lastTitle && this.lastTitle) { // only mag 6> can be sent to 7 fa and coords

               if (mgntd > 6) {
                  this.client.sendMessage( //replace with sendMultiple after testing
                     "5217223784886-1598620689@g.us", //Change
                     `🚨🚨🚨 Alerta *sismo* Tiempo Real\n\n*${title}*`
                  );
                  this.client.sendMessage( //replace with sendMultiple after testing
                     "5217221508888-1431783389@g.us", //Change
                     `🚨🚨🚨 Alerta *sismo* Tiempo Real\n\n*${title}*`
                  );
               } else {
                  this.client.sendMessage(
                     "5217291065569@c.us", //Just you
                     `🚨 Alerta sismo *menor* Tiempo Real\n\n*${title}*`
                  );
               }
            }
         } else if (this.lastTitle) {
            if (title !== this.lastTitle) {
               this.client.sendMessage(
                  "5217291065569@c.us", //Just you
                  `🚨 Alerta sismo *menor* Tiempo Real\n\n*${title}*`
               );
            }
         }
         this.lastTitle = title;
      }, 60000);
   }
   protected async _postal(): void {

      var db = mysql.createConnection({
         host: "localhost",
         user: "root",
         password: "Nicole10*",
         database: 'casitaiedis',
         charset: 'utf8mb4'
      });
      var data = [];
      const promise = new Promise((resolve, reject) => {
         db.query("select * from ((SELECT id, de as 'text', concat('521',para,'@c.us') as 'to' FROM xmas WHERE sent = '0' and error = '0' LIMIT 10) A INNER JOIN (SELECT x, y, path as imagePath, color FROM xmas_postales ORDER BY RAND() LIMIT 1) B) where id is not null")
            .on("error", (err) => {
               console.error(err);
               reject(err);
            })
            .on("result", (row) => {
               db.pause();
               data.push(row);
               db.resume();
            })
            .on("end", () => {
               resolve(data);
            });
      });
      var data = await promise;

      console.log('Batch of ' + data.length);
      const promises = [];
      for (var i = 0; i < data.length; i++) {
         promises.push(new Promise(async (resolve, reject) => {
            var imagePath = data[i].imagePath;
            var x = data[i].x;
            var y = data[i].y;
            var color = data[i].color;
            var text = data[i].text;
            var to = data[i].to;
            var id = data[i].id;
            if (!id) {
               resolve();
            }
            console.log(`Sending to ${to} from ${text} at ${x} ${y}`);
            await this.delay();
            try {
               // var buffer = await fetch(`https://bot.casitaapps.com/postal?x=${x}&y=${y}&imagePath=${imagePath}&text=${text}`).then(res => res.buffer());
               // var media = new MessageMedia('image/png', buffer);
               // await this.client.sendMessage(to, media);

               var canvas = createCanvas(1024, 576);
               var ctx = canvas.getContext('2d');
               var image = await loadImage(imagePath);

               ctx.drawImage(image, 0, 0, 1024, 576);
               ctx.fillStyle = color;
               ctx.font = 'bold 30pt Menlo';
               ctx.fillText(text, x, y);

               const buffer = canvas.toBuffer('image/png');
               const tmpobj = tmp.fileSync();
               await writeFile(tmpobj.name, buffer);
               const media = await MessageMedia.fromFilePath(tmpobj.name);
               media.mimetype = 'image/png'
               await this.client.sendMessage(to, media);

               console.log(`Sent to ${to}`);
               db.query(`UPDATE xmas SET sent = '1' WHERE id = '${id}'`).on("error", (err) => {
                  console.error(err);
               })
               resolve();
            } catch (err) {

               console.log('Errorzote', err);

               db.query(`UPDATE xmas SET error = '1' WHERE id = '${id}'`).on("error", (err) => {
                  console.error(err);
               })
               resolve();
            }
         }));
      }
      await Promise.all(promises);
      db.end();
      this._clearMysql();

   }
   protected async _sendMultiple(chatIds, message, args): void {
      for (var i = 0; i < chatIds.length; i++) {
         await this.delay().then((e) => {
            this.client.sendMessage(
               chatIds[i],
               message,
               args
            );
         });
      }
   }
}