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 document personalitzat i el passem a PDF

En aquest exemple agafarem un document plantilla que tenim a Google Drive, en farem una còpia que personalitzarem amb les dades de l'usuari que ho sol·liciti (mantenint intacta la plantilla). Un cop creat el document personalitzat, el passarem a PDF i el posarem a disposició de l'usuari. Després esborrarem la versió personalitzada. Veurem tres maneres de posar-lo a disposició del sol·licitant. També veurem dues maneres de personalitzar el document. S'ha agafat l'Id de Telegram com a identificador de l'usuari perquè així tenim un identificador únic per usuari i, a més, evitem la necessitat de posar paràmetres a la comanda.

El document de la plantilla té una sèrie de camps que són els que es poden personalitzar. En el nostre cas hem posat tres paràmetres i hem situat el seu nom entre claus. Podem marcar els paràmetres com vulguem (en lloc de les claus) però ens hem d'assegurar que no apareixeran els paràmetres marcats en altres llocs del document. Els tres paràmetres del nostre exemple són:

Paràmetre Descripció
{nom} Nom i cognoms de l'usuari
{hora} Hora en la que s'ha fet l'activitat
{data} Data en què s'ha fet el document i l'activitat

També tindrem un full de càlcul amb les dades de cada un dels possibles usuaris. Les columnes del full són:

Columna Contingut
0 Id de Telegram de l'usuari
1 Nom i cognoms de la persona
2 Data en què s'ha fet el document i l'activitat
3 Hora en la que s'ha fet l'activitat
4 Adreça de correu electrònic de l'usuari

Podem posar tants paràmetres com ens convingui. En alguns casos potser ens interessarà afegir camps, en altres potser separarem el nom i els cognoms en camps diferents, etc. Basant-nos en aquest exemple podem fer cartes, certificats d'assistència i altres documents personalitzats.

Aquest script fa servir només la comanda /cert però es podria ampliar amb més comandes que li permetessin fer altres funcions. Per exemple, es podria fer servir el mateix script per inscriure's a l'activitat de la qual després s'obté el certificat d'assistència.

La primera cosa que cal fer és crear el bot de conversa, després cal crear l'script per acabar assignant l'script al bot de conversa. Anem a veure com seria l'script.

Atenció: Si el PDF triga un cert temps a crear-se, ens podem trobar que quan el programa l'intenta enviar encara no estigui llest. Per evitar el problema, podem fer un bucle d'espera mentre es crea el document; com es fa en les línies marcades en color en el programa d'aquest exemple.

Primera versió

La funció doPost només mira quina és la comanda rebuda i, si és l'esperada, crida la funció que genera el document. El primer que fa la funció és buscar l'usuari a la taula. Si el troba, recopila totes les dades necessàries de la filera corresponent. Llavors envia un missatge a l'usuari on li indica que s'està preparant el document, aquest missatge és convenient perquè la creació del document triga alguns segons. En aquesta primera versió es crea un document provisional buit que acabarà contenint la versió personalitzada del document. Després es van copiant, un a un, els paràgrafs del document original (del que necessitem l'identificador) sobre el nou mentre es substitueix, si escau, el paràmetre pel seu valor. Hem d'entendre la paraula paràgraf en sentit ampli, és a dir un conjunt de text que forma una unitat tancada. Un cop acabat de crear el document personalitzat, en genera una versió PDF que guarda en la carpeta indicada (amb el seu identificador). Seguidament agafa les dades (adreça URL i identificador) del fitxer PDF i esborra el document provisional (l'envia a la paperera). Per acabar, envia un missatge a l'usuari per dir-li que el document ja està i donant-li l'enllaç per descarregar-lo.

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 
var ssId = "^^ThsoSjkeMSfwEKy4mn_4QEYH96sxv3VURqE3WHCTswDA";  // Identificador del full de càlcul
var id_plantilla = "1Di13cpVu3oY-AN7wdg-cPp8pmNqNmYTVh7FDkkq3cX8";  // Document que serveix de plantilla
var id_carpeta = "^^Hlod5Y4qEsLF9HrIsE6oYQa32f6NHeo";  // Carpeta on guardarem el PDF
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
  var par = comanda[1];  // Paràmetre
  if(cmd == '/cert'){
    preparaCertif(id);  // Preparem el certificat
    realitzat = true;
  }
  if(!realitzat){
    var resposta = "Comanda desconeguda";
    sendText(id,resposta);  
  }
}
// El paràmetre usuari és el Id i serveix tant per buscar 
//    el certificat com per enviar la resposta
function preparaCertif(usuari){
  var sh = SpreadsheetApp.openById(ssId).getSheetByName("examen");  // Obrim el full de càlcul
  var dades = sh.getDataRange().getValues();  // Agafem els valors
  var resposta = "";
  // Primer busquem a quina fila estan les dades de l'usuari
  // Si el resultat és 0 vol dir que no hi és
  var fila = 0;
  for(var i in dades){
    var row = dades[i];  // Agafa una filera
    var num_usuari = row[0];   // Id de l'usuari
    if(num_usuari == usuari){
      fila = i;  // Aquesta és la filera corresponent a l'usuari
    }
  }
  if(fila == 0){  // Si no l'hem trobat
    resposta = "No tens dret al document demanat";
    sendText(usuari,resposta);  
  } else {
    resposta = "Estem preparant el document";
    sendText(usuari,resposta);  
    var row = dades[fila];  // Agafa les dades
    var num = row[0];
    var nom = row[1];
    var data = row[2];
    var hora = row[3];
    var correu = row[4];
    var plantilla = DocumentApp.openById(id_plantilla);   // Obrim la plantilla
    var titol = "cert_" + num;  // Posa un títol que inclou el número d'usuari, per poder saber de qui és
    var doc_prov = DocumentApp.create(titol);  // Crea el document provisional
    var id_doc_prov = doc_prov.getId();  // N'obté l'identificador
    var plantilla_paragrafs = plantilla.getBody().getParagraphs();  // Agafa el contingut de la plantilla
    // Carreguem tots els paràgrafs de la Plantilla
    for(var j = 0; j < plantilla_paragrafs.length; j++){  // Per a tots els paràgrafs del document
      var parag = plantilla_paragrafs[j].copy();  // Guarda una còpia del paràgraf a la variable
      parag = parag.replaceText("{nom}",nom);  // Substitueix el nom
      parag = parag.replaceText("{hora}",hora);  // Substitueix l'hora
      parag = parag.replaceText("{data}",data);  // Substitueix la data
      doc_prov.getBody().appendParagraph(parag);  // Posa el paràgraf al nou document
    }
    doc_prov.saveAndClose();  // Guarda i tanca el document 
    // Genera el contingut PDF apartir del document Final de la combinació
    var docblob = DriveApp.getFileById(id_doc_prov).getAs('application/pdf'); 
    docblob.setName(titol + ".pdf");  // Posa el nom del fitxer
    // Crea el fitxer PDF a partir del contingut guardat abans
    var file = DriveApp.getFolderById(id_carpeta).createFile(docblob);   
    var url_fitxer = file.getDownloadUrl();  // Adreça per descarregar el PDF
    var id_fitxer = file.getId();  // Identificador del document PDF
    DriveApp.getFileById(id_doc_prov).setTrashed(true);  // Marca com a esborrat el document provisional
    resposta = "El document està llest, el pots descarregar a " + url_fitxer;
    sendText(usuari,resposta);  
  }    
}   
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);
}

Segona versió

En la primera versió li donem a l'usuari un enllaç per descarregar el document. Una alternativa seria fer servir un botó de teclat en línia. En aquesta versió, a més, en lloc de generar el document personalitzat paràgraf a paràgraf el que farem serà copiar el document de la plantilla i modificar la còpia. Aquesta forma de crear el document és més eficient ja que triga, aproximadament, un segon menys en executar-se (en el cas del document que hem fet servir per provar-ho).

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 
var ssId = "^^ThsoSjkeMSfwEKy4mn_4QEYH96sxv3VURqE3WHCTswDA";  // Identificador del full de càlcul
var id_plantilla = "1Di13cpVu3oY-AN7wdg-cPp8pmNqNmYTVh7FDkkq3cX8";  // Document que serveix de plantilla
var id_carpeta = "^^Hlod5Y4qEsLF9HrIsE6oYQa32f6NHeo";  // Carpeta on guardarem el PDF
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
  var par = comanda[1];  // Paràmetre
  if(cmd == '/cert'){
    preparaCertif(id);
    realitzat = true;
  }
  if(!realitzat){
    var resposta = "Comanda desconeguda";
    sendText(id,resposta);  
  }
}
// El paràmetre usuari és el Id i serveix tant per buscar 
//    el certificat com per enviar la resposta
function preparaCertif(usuari){
  var sh = SpreadsheetApp.openById(ssId).getSheetByName("examen");  // Obre el full de càlcul
  var dades = sh.getDataRange().getValues();  // Agafa el contingut
  var resposta = "";
  // Primer busquem a quina fila estan les dades de l'usuari
  // Si el resultat és 0 vol dir que no hi és
  var fila = 0;
  for(var i in dades){  // Recorre totes les dades
    var row = dades[i];  // Agafa una filera
    var num_usuari = row[0];  // Identificador de l'usuari
    if(num_usuari == usuari){
      fila = i;  // Aquesta és la filera de l'usuari
    }
  }
  if(fila == 0){  // Si no l'hem trobat
    resposta = "No tens dret al document demanat";
    sendText(usuari,resposta);  
  } else {
    resposta = "Estem preparant el document";
    sendText(usuari,resposta);  
    var row = dades[fila];  // Agafa la filera
    var num = row[0];
    var nom = row[1];
    var data = row[2];
    var hora = row[3];
    var correu = row[4];
    var plantilla = DriveApp.getFileById(id_plantilla);  // Agafa la plantilla
    var titol = "cert_" + num;  // Posa un títol que inclou el número d'usuari, per poder saber de qui és
    var doc_prov = plantilla.makeCopy(titol);  // Creem la còpia de la plantilla
    var id_doc_prov = doc_prov.getId();  // Agafem l'identificador del document creat
    var document = DocumentApp.openById(id_doc_prov);   // Obrim la plantilla
    var contingut = document.getBody();  // Agafem el contingut del document
    contingut.replaceText("{nom}",nom);  // Substitueix el nom
    contingut.replaceText("{hora}",hora);  // Substitueix l'hora
    contingut.replaceText("{data}",data);  // Substitueix la data
    document.saveAndClose();  // Guarda i tanca el document 
    // Genera el contingut PDF apartir del document Final de la combinació
    var docblob = DriveApp.getFileById(id_doc_prov).getAs('application/pdf'); 
    docblob.setName(titol + ".pdf");  // Posa el nom al document PDF
    // Crea el fitxer PDF a partir del contingut guardat abans
    var file = DriveApp.getFolderById(id_carpeta).createFile(docblob);   
    var url_fitxer = file.getDownloadUrl();  // Adreça per baixar el fitxer
    var id_fitxer = file.getId();  // Identificador del fitxer
    DriveApp.getFileById(id_doc_prov).setTrashed(true);
	// Creem el teclat amb la tecla per baixar-lo
    var tecles = {"inline_keyboard":[ [{"text":"Descarrega","url":url_fitxer}] ]};
    var titol = "El document està llest";  // Títol del teclat
    sendText(usuari,titol,tecles);  
  }    
}   
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);
}

Tercera versió

En aquesta versió el document s'envia per correu electrònic com a arxiu adjunt.

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 
var ssId = "^^ThsoSjkeMSfwEKy4mn_4QEYH96sxv3VURqE3WHCTswDA";  // Identificador del full de càlcul
var id_plantilla = "1Di13cpVu3oY-AN7wdg-cPp8pmNqNmYTVh7FDkkq3cX8";  // Document que serveix de plantilla
var id_carpeta = "^^Hlod5Y4qEsLF9HrIsE6oYQa32f6NHeo";  // Carpeta on guardarem el PDF
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
  var par = comanda[1];  // Paràmetre
  if(cmd == '/cert'){
    preparaCertif(id);  // Generem el document
    realitzat = true;
  }
  if(!realitzat){
    var resposta = "Comanda desconeguda";
    sendText(id,resposta);  
  }
}
// El paràmetre usuari és el Id i serveix tant per buscar 
//    el certificat com per enviar la resposta
function preparaCertif(usuari){
  var sh = SpreadsheetApp.openById(ssId).getSheetByName("examen");  // Obre el full de càlcul
  var dades = sh.getDataRange().getValues();  // Agafa el contingut
  var resposta = "";
  // Primer busquem a quina fila estan les dades de l'usuari
  // Si el resultat és 0 vol dir que no hi és
  var fila = 0;
  for(var i in dades){  // Recorre totes les dades
    var row = dades[i];  // Agafa una filera
    var num_usuari = row[0];  // Identificador de l'usuari
    if(num_usuari == usuari){
      fila = i;  // Aquesta és la filera que correspon a l'usuari
    }
  }
  if(fila == 0){  // Si no l'hem trobat
    resposta = "No tens dret al document demanat";
    sendText(usuari,resposta);  
  } else {
    resposta = "Estem preparant el document";
    sendText(usuari,resposta);  
    var row = dades[fila];  // Agafa les dades de l'usuari
    var num = row[0];
    var nom = row[1];
    var data = row[2];
    var hora = row[3];
    var correu = row[4];
    var plantilla = DriveApp.getFileById(id_plantilla);  // Agafa el document de la plantilla
    var titol = "cert_" + num;  // Posa un títol que inclou el número d'usuari, per poder saber de qui és
    var doc_prov = plantilla.makeCopy(titol);  // Fa una còpia de la plantilla
    var id_doc_prov = doc_prov.getId();  // Identificador del document
    var document = DocumentApp.openById(id_doc_prov);   // Obrim el document
    var contingut = document.getBody();  // Agafem el contingut del document
    contingut.replaceText("{nom}",nom);  // Substitueix el nom
    contingut.replaceText("{hora}",hora);  // Substitueix l'hora
    contingut.replaceText("{data}",data);  // Substitueix la data
    document.saveAndClose();  // Guarda i tanca el document 
    // Genera el contingut PDF apartir del document Final de la combinació
    var docblob = DriveApp.getFileById(id_doc_prov).getAs('application/pdf'); 
    docblob.setName(titol + ".pdf");  // Posa el nom al fitxer PDF
    // Crea el fitxer PDF a partir del contingut guardat abans
    var file = DriveApp.getFolderById(id_carpeta).createFile(docblob);   
    var url_fitxer = file.getDownloadUrl();  // Adreça per descarregar el PDF
    var id_fitxer = file.getId();  // Identificador del fitxer PDF
    DriveApp.getFileById(id_doc_prov).setTrashed(true);  // Marca com esborrat el document provisional
    var destinatari = correu;  // Agafa l'adreça a la que l'hem d'enviar
    // Aquest és el nom del remitent,
    //   l'adreça és la del compte de Google amb el que hem creat l'script
    var remitent = "Generador automàtic de documents";
    var titol = "El teu certificat";
    var text = "Adjunt trobaràs el document sol·licitat.";
    var adjunt = DriveApp.getFileById(id_fitxer);  // Agafa el fitxer
    MailApp.sendEmail(destinatari, titol, text, {
      name: remitent,
      attachments: [adjunt.getAs(MimeType.PDF)]
    });  // Envia el correu
    resposta = "T'hem enviat el document per correu electrònic";
    sendText(usuari,resposta);  
  }    
}   
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);
}

En aquesta versió podríem esborrar el PDF (enviar-lo a la paperera) un cop ja l'hem enviat a l'usuari. En les primeres versions també podríem fer que l'usuari ens avisés (amb una comanda o amb un botó) quan hagués descarregat el document per poder-lo esborrar.

 

 

 

 

 

 

 

 

 

 

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