Bots de conversa de Telegram amb Google Apps Script

Bots de conversa Exemples Dades pràctiques   Recursos CITCEA
Google Apps Script Projectes Interacció   Inici

Obtenim previsió meteorològica tractant dades XML

En aquest exemple tractarem les dades XML obtingudes del web del Servei Meteorològic de Catalunya per obtenir la previsió meteorològica per a l'endemà en una comarca concreta. La comanda que s'envia al bot de conversa és /temps seguida de part del nom de la comarca desitjada. Per exemple:

/temps alt rib
/temps pla est

La cerca de la comarca no té en compte la diferència entre majúscules i minúscules. En cas que els paràmetres puguin correspondre a més d'una comarca ens mostrarà les dades de la darrera que s'hi correspongui, seguint l'ordre del fitxer XML.

La comanda que farem servir serà aquesta:

https://static-m.meteo.cat/content/opendata/ctermini_comarcal.xml

La consulta torna una informació molt llarga. Les dades estan en format XML que podem processar, per exemple, amb XML Formatter si en volem veure l'estructura per saber què ens interessa.

De les dades XML rebudes, primer revisarem la llista de comarques per trobar la posició a la llista de la comarca desitjada. Després buscarem la previsió de la comarca corresponent. En el fitxer solen venir les previsions de dos dies i caldrà trobar quina és la que correspon a l'endemà. Llavors agafarem les dades més rellevants de la predicció.

Si suposem que el resultat de tractar el format XML el tenim a la variable document, podem extreure un vector amb la informació de les comarques:

  var document = XmlService.parse(response);
  var root = document.getRootElement();
  var comarques = root.getChildren("comarca");

D'aquest vector en podem analitzar cada component i extreure'n el nom de la comarca:

  var nomCom = comarques[i].getAttribute("nomCOMARCA").getValue();

També podem extreure un vector que conté les dades de predicció de cada comarca i n'agafem la que correspon a la comarca que ens interessa.

  var previsio = root.getChildren("prediccio");
  var prevCom = previsio[punter];

En aquest fitxer hi ha dues prediccions etiquetades amb la paraula variable. De cada una mirarem la data per veure quina és la que correspon a l'endemà:

  var previsions = prevCom.getChildren("variable");
  var prevDema = previsions[i].getAttribute("data").getValue();

D'aquí també obtindrem les dades que enviarem a l'usuari, que seran les temperatures màxima i mínima i els símbols gràfics corresponents a les previsions del matí i de la tarda.

  var simbolmati = previsions[pntr].getAttribute("simbolmati").getValue();
  var simboltarda = previsions[pntr].getAttribute("simboltarda").getValue();
  var tempmax = previsions[pntr].getAttribute("tempmax").getValue();
  var tempmin = previsions[pntr].getAttribute("tempmin").getValue();

El codi de l'script és el següent:

var token = "^^34328844:AAFIpk-e7j3UZtYQYQaTduf4hEhnDqIcNXI"; // API Token de Telegram 
var telegramUrl = "https://api.telegram.org/bot" + token;  // URL que comunica el nostre bot amb Telegram  
var realitzat = false;
function doPost(e){
  var data = JSON.parse(e.postData.contents);  // Llegeix les dades rebudes per JSON i les guarda
  var text = data.message.text;  // Comanda enviada
  var id = data.message.chat.id;  // Identificador de la finestra d'on prové el missatge 
  var id_usuari = data.message.from.id; // Identificador de l'usuari
  var id_missatge = data.message.message_id; // Identificador del missatge
  var lang = data.message.from.language_code ;  // Idioma de l'usuari 
  var nom_usr = data.message.from.first_name ;  // Nom de l'usuari
  var location = data.message.location;  // Localització de l'usuari (si es sap) 
  var comanda = text.split(" ");  // El signe @ separa la comanda dels paràmetres 
  var cmd = comanda[0];  // Comanda
  if(cmd == '/help'){
    realitzat = true;
    expli(id);
  }
  if(cmd == '/temps'){
    if(comanda.length < 2){  // Si no hi ha paràmetre
      realitzat = true;
      expli(id);  // Envia una explicació
    } else {
      meteo(id,comanda);  // Mostra la predicció
      realitzat = true;
    }
  }
  if(!realitzat){
    var resposta = "Comanda desconeguda";
    sendText(id,resposta);  
  }
}
function meteo(id, comar){
  var nc1 = "";
  var nc2 = "";
  // Passa el nom de la comarca a minúscules per facilitar la comparació
  if (comar[1] != undefined){
    nc1 = comar[1].toLowerCase();
  } 
  if (comar[2] != undefined){
    nc2 = comar[2].toLowerCase();
  } 
  // Adreça on hi ha les dades
  var peticio = "https://static-m.meteo.cat/content/opendata/ctermini_comarcal.xml";
  var response = UrlFetchApp.fetch(peticio).getContentText(); // Carrega la resposta a la petició
  var document = XmlService.parse(response);  // Tracta les dades XML rebudes
  var root = document.getRootElement();  // Arrel de l'estructura de dades
  var comarques = root.getChildren("comarca");  // Informació de les comarques
  var resposta = "";
  var punter = -1;
  for (var i = 0; i < comarques.length; i++){  // Mira totes les comarques
    var nomCom = comarques[i].getAttribute("nomCOMARCA").getValue().toLowerCase();  // Nom de la comarca
    if((nomCom.indexOf(nc1) >-1) && (nomCom.indexOf(nc2) >-1)){  // Si hi ha alguna coincidència
      punter = i;  // Posició de la coincidència
    }
  }
  if(punter == -1){   // Si no l'ha trobat
    resposta = "Comarca no trobada";
    sendText(id,resposta);
    return;
  }
  // Necessitem la data de demà
  // No podem sumar 1 al dia perquè demà podria ser un mes diferent que avui
  // Agafem la data sumant a la d'avui els mil·lisegons que dura un dia
  var ara = new Date();  // Avui
  var ms_dia = 1000 * 60 * 60 * 24;
  var dema = new Date(ara.getTime() + ms_dia);
  var dia = dema.getDate();
  var mes = dema.getMonth() + 1;  // Compta els mesos de 0 a 11
  var any = dema.getFullYear();
  var data = "";
  // Posa la data en el format requerit
  if (dia < 10){
    data = data + "0";
  }
  data = data + dia + "-";
  if (mes < 10){
    data = data + "0";
  }
  data = data + mes + "-" + any;
  var previsio = root.getChildren("prediccio");  // Busca la predicció
  var prevCom = previsio[punter];  // Agafa la de la comarca demanada
  var previsions = prevCom.getChildren("variable");  // Agafa les dades
  var pntr = -1;  // Si no ho troba valdrà -1
  for (var i = 0; i < previsions.length; i++){  // Mira totes les respostes
    if (previsions[i].getAttribute("data").getValue() == data){  // Comprova la data
      pntr = i;  // Índex de la data desitjada
    }
  }
  if(pntr == -1){  
    resposta = "Dades no trobades";
    sendText(id,resposta);
    return;
  }
  // Anem a mostrar els resultats
  var nomComarca = comarques[punter].getAttribute("nomCOMARCA").getValue();  // Nom de la comarca
  var simbolmati = previsions[pntr].getAttribute("simbolmati").getValue();  // Símbol de predicció matí
  var simboltarda = previsions[pntr].getAttribute("simboltarda").getValue();  // Símbol de predicció tarda
  var tempmax = previsions[pntr].getAttribute("tempmax").getValue();  // Temperatura màxima
  var tempmin = previsions[pntr].getAttribute("tempmin").getValue();  // Temperatura mínima
  // Preparem la resposta
  resposta = "<b>Temps per a demà (" + data + ") a " + nomComarca + "</b>\n";
  resposta = resposta + "Temperatura màxima:  " + tempmax +" °C\n";
  resposta = resposta + "Temperatura mínima:  " + tempmin +" °C\n";
  sendText(id,resposta);  // Envia la primera part 
  var caption = "Previsió matí"; // Missatge que acompanya al codi 
  // Imatge del símbol
  var imat = "https://static-m.meteo.cat/assets-w3/images/meteors/estatcel/" + simbolmati;
  var response = UrlFetchApp.fetch(imat); // Carrega la imatge corresponent a la url generada 
  var binaryData = response.getContent();  // Imatge en dades binàries
  // La funció newBlob té tres paràmetres: les dades, el tipus de dades i el nom que li volem donar
  // carrega la imatge com a dades binaries en una variable 
  var blob_data = Utilities.newBlob(binaryData, 'image/png', caption); 
  sendBlobFile(id,blob_data,caption);  // Enviem la imatge al Telegram però amb  format binari (BLOB) 
  var caption = "Previsió tarda";  // Missatge que acompanya al codi 
  // Imatge del símbol
  var imat = "https://static-m.meteo.cat/assets-w3/images/meteors/estatcel/" + simboltarda;
  var response = UrlFetchApp.fetch(imat); // Carrega la imatge corresponent a la url generada 
  var binaryData = response.getContent();   // Imatge en dades binàries
  // La funció newBlob té tres paràmetres: les dades, el tipus de dades i el nom que li volem donar
  // carrega la imatge com a dades binaries en una variable 
  var blob_data = Utilities.newBlob(binaryData, 'image/png', caption); 
  sendBlobFile(id,blob_data,caption); // Enviem la imatge al Telegram però amb  format binari (BLOB) 
}
function expli(id){
  var resposta = "<b>Per consultar la previsió per a demà:</b>\n";
  resposta =  resposta + "/temps comarca\n\n";
  resposta =  resposta + "Exemples:\n";
  resposta =  resposta + "/temps alt rib\n";
  resposta =  resposta + "/temps pla est\n";
  sendText(id,resposta);  
}   
function sendBlobFile(chatId,blob_data,caption){
  // La funció newBlob té tres paràmetres: les dades,
  //   el tipus de dades i el nom que li volem donar
  var payload = {
    method: "sendPhoto",
    chat_id: String(chatId),
    photo: blob_data,
    caption: caption,
    parse_mode: "HTML"
  };
  var options = {
    method: "POST",
    payload: payload,
    muteHttpExceptions: true
  };
  UrlFetchApp.fetch( telegramUrl + '/', options);
}
function sendText(chatId,text_env,keyBoard){  // Funció que prepara per enviar un text o un teclat a Telegram 
  keyBoard = keyBoard || 0;
  if(keyBoard.inline_keyboard || keyBoard.keyboard){
    var data = {
      method: "post",
      payload: {
        method: "sendMessage",
        chat_id: String(chatId),
        text: text_env,
        parse_mode: "HTML",
        reply_markup: JSON.stringify(keyBoard)
      }
    }
  } else {
    var data = {
      method: "post",
      payload: {
        method: "sendMessage",
        chat_id: String(chatId),
        text: text_env,
        parse_mode: "HTML"
      }
    }
  }
  UrlFetchApp.fetch( telegramUrl + '/', data);
}

 

 

 

 

 

 

 

 

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.