Bots de conversa de Telegram amb Google Apps Script

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

Creem un mapa de Google amb rutes

En aquest exemple cercarem una ruta a peu amb dos punts de pas, la posarem en un mapa de Google i l'enviarem a l'usuari com a imatge en format de dades binàries (BLOB). La imatge que generarem és la següent:

Mapa

En aquest cas, per simplificar el programa, els punts estan definits en el propi programa. Podrien, però, estar en un full de càlcul; d'aquesta manera el programa podria agafar uns punts diferents segons els paràmetres introduïts per l'usuari. Per marcar els punts fem servir lletres, començant per l'A. Podríem crear un vector amb les lletres dels marcadors però si les volem consecutives és probablement més fàcil agafar el codi ASCII de la lletra A i anar-lo incrementant.

El programa é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 bot de conversa amb Telegram 
function mapa(){
  var codi_etiqueta = 'A'.charCodeAt();  // Agafa el codi ASCII de la lletra A
  var adre = Maps.newDirectionFinder();  // Creem un cercador de rutes
  // Definim els punts de pas
  adre.setOrigin("FME UPC");  // Origen
  adre.addWaypoint("ETSEIB UPC");
  adre.addWaypoint("ETSECCPB UPC");
  adre.setDestination("FIB UPC");  // Final
  adre.setMode(Maps.DirectionFinder.Mode.WALKING);  // Ruta a peu
  var recorreguts = adre.getDirections();  // Agafem les rutes
  var ruta = recorreguts.routes[0];  // Agafem la ruta recomanada
  var map = Maps.newStaticMap();  // Creem un mapa
  map.setSize(600, 600);  // Mides del mapa
  // Hi ha una pota de la ruta entre cada dos punts del recorregut
  // Recorrem les potes
  for (var i = 0; i < ruta.legs.length; i++) {  // Mirem totes les potes
    var pota = ruta.legs[i];  // N'agafem una
    if (i == 0) {
      // El punt origen només el marquem per a la primera pota
      var etiqueta = String.fromCharCode(codi_etiqueta);  // Lletra per marcar el punt
      map.setMarkerStyle(Maps.StaticMap.MarkerSize.MID, Maps.StaticMap.Color.GREEN, etiqueta);
      map.addMarker(pota.start_location.lat, pota.start_location.lng);  // Afegim la marca
      codi_etiqueta++;  // Lletra següent
    }
    // El punt final el marquem a totes les potes
    etiqueta = String.fromCharCode(codi_etiqueta);  // Lletra per marcar el punt
    map.setMarkerStyle(Maps.StaticMap.MarkerSize.MID, Maps.StaticMap.Color.GREEN, etiqueta);
    map.addMarker(pota.end_location.lat, pota.end_location.lng);  // Afegim la marca
    codi_etiqueta++;  // Lletra següent
  }
  map.setPathStyle(4, Maps.StaticMap.Color.RED, null);  // Color de la ruta
  map.addPath(ruta.overview_polyline.points);  // Dibuixem la ruta
  var mapa_blob =  map.getBlob();  // Converteix el mapa a dades binàries 
  return mapa_blob;
}
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 realitzat = false;
  if(text == '/mapa'){
    var blob = mapa();  // Crea el mapa
    var descrip = "Mapa";  // Títol
    sendBlobFile(id,blob,descrip);  // Ho envia a Telegram
    realitzat = true;
  }
  if (!realitzat){
    var resposta = "Comanda desconeguda";
    sendText(id,resposta);
  }
}
function sendText(chatId,text_env,keyBoard){  // Funció que envia 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);
}
function sendBlobFile(chatId,blob_data,caption){
  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);
}

En el següent exemple la ruta, en vehicle, tindrà alternatives. Mostrarem les rutes en colors diferents. Generarem tres imatges, una amb la ruta completa, una amb el detall de la sortida i la darrera amb el detall de l'arribada. Les imatges que generarem són les següents:

Mapa

Mapa

Mapa

Observem que quan dues rutes es superposen apareix un color intermedi. També envia un text descriptiu:

Ruta 1 (vermell):
Recorregut: 26,9 km
Durada: 31 min

Ruta 2 (blau):
Recorregut: 36,9 km
Durada: 34 min

Ruta 3 (verd):
Recorregut: 26,4 km
Durada: 35 min

var token = "^^34328844:AAFIpk-e7j3UZtYQYQaTduf4hEhnDqIcNXI"; // API Token de Telegram 
var telegramUrl = "https://api.telegram.org/bot" + token;  // URL que comunica el bot de conversa amb Telegram 
function mapa(id_usr){
  // Definim quatre colors, i els seus noms, per a les rutes
  var colMaps = Array(4);
  colMaps[0] = Maps.StaticMap.Color.RED;
  colMaps[1] = Maps.StaticMap.Color.BLUE;
  colMaps[2] = Maps.StaticMap.Color.GREEN;
  colMaps[3] = Maps.StaticMap.Color.BLACK;
  var colors = ["vermell", "blau", "verd", "negre"];
  var adre = Maps.newDirectionFinder();  // Crea un cercador de rutes
  adre.setAlternatives(true);  // Volem que ens mostri diverses alternatives
  adre.setOrigin("ETSEIB UPC");  // Inici de la ruta
  adre.setDestination("ESEIAAT UPC");  // Final de la ruta
  adre.setMode(Maps.DirectionFinder.Mode.DRIVING);  // Anirem en vehicle
  var recorreguts = adre.getDirections();  // Agafem les rutes
  var map = Maps.newStaticMap();  // Crea un mapa
  map.setSize(600, 600);  // Mides del mapa
  var descrip = "";
  for (var i = 0; i < recorreguts.routes.length; i++) {  // Mirem totes les rutes
    var ruta = recorreguts.routes[i];  // Agafem una ruta
    var pota = ruta.legs[0];  // Amb dos punts, només hi ha una pota
    map.setPathStyle(4, colMaps[i % colMaps.length], null);  // Format de la ruta
    var num = i + 1;  // El número de ruta comença en 1
    descrip = descrip + "Ruta " + num + " (" + colors[i] + "):\n";
    descrip = descrip + "Recorregut: " + pota.distance.text + "\n";
    descrip = descrip + "Durada: " + pota.duration.text + "\n\n";
    descrip = descrip.replace(".",",");  // Canviem punts per comes (SI)
    descrip = descrip.replace("mins","min");  // Sinó surt "mins", que no és correcte
    if (i == 0) {
      // Només marquem els punts un cop, l'inici amb I i el final amb F
      map.setMarkerStyle(Maps.StaticMap.MarkerSize.MID, colMaps[0], "I");
      map.addMarker(pota.start_location.lat, pota.start_location.lng);
      map.setMarkerStyle(Maps.StaticMap.MarkerSize.MID, colMaps[0], "F");
      map.addMarker(pota.end_location.lat, pota.end_location.lng);
    }
    map.addPath(ruta.overview_polyline.points);  // Afegim la ruta
  }
  sendText(id_usr, descrip);  // Abans dels mapes enviem el text
  var mapa_blob =  map.getBlob(); // Converteix el mapa a dades binaries 
  var caption = "Ruta";  // Títol
  sendBlobFile(id_usr,mapa_blob,caption);  // Enviem el primer mapa
  map.setZoom(14);  // El segon mapa és més gros
  map.setCenter("ETSEIB UPC");  // i centrat a l'inici
  var mapa_blob =  map.getBlob(); // Converteix el mapa a dades binaries 
  var caption = "Detall inici";  // Títol
  sendBlobFile(id_usr,mapa_blob,caption);  // Enviem el segon mapa
  map.setCenter("ESEIAAT UPC");  // El tercer mapa es centra al final
  var mapa_blob =  map.getBlob(); // Converteix el mapa a dades binaries 
  var caption = "Detall final";   // Títol
  sendBlobFile(id_usr,mapa_blob,caption);  // Enviem el tercer mapa
}
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 realitzat = false;
  if(text == '/mapa'){
    mapa(id);  // Creem el mapa
    realitzat = true;
  }
  if (!realitzat){
    var resposta = "Comanda desconeguda";
    sendText(id,resposta);
  }
}
function sendText(chatId,text_env,keyBoard){  // Funció que envia 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);
}
function sendBlobFile(chatId,blob_data,caption){
  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);
}

 

 

 

 

 

 

 

 

 

 

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