| Bots de conversa | Exemples | Dades pràctiques | Recursos CITCEA | |
| Google Apps Script | Projectes | Interacció | Inici |
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);
}

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