Envía notificaciones para una app web con Cloud Messaging y Cloud Functions

1. Descripción general

En este codelab, aprenderás a usar Cloud Functions para Firebase para agregar funcionalidad a una app web de chat mediante el envío de notificaciones a los usuarios de la app de chat.

3b1284f5144b54f6.png

Qué aprenderás

  • Cómo usar el SDK de Firebase para crear funciones de Google Cloud Functions
  • Cómo activar funciones de Cloud Functions basadas en eventos de Auth, Cloud Storage y Cloud Firestore
  • Cómo agregar compatibilidad con Firebase Cloud Messaging a su aplicación web

Requisitos

  • Una tarjeta de crédito Cloud Functions para Firebase requiere el plan Blaze de Firebase, lo que significa que deberás habilitar la facturación en tu proyecto de Firebase con una tarjeta de crédito.
  • El editor de texto o IDE que prefieras, como WebStorm, Atom o Sublime
  • Una terminal para ejecutar comandos de shell con NodeJS v9 instalado
  • Un navegador como Chrome
  • El código de muestra. Consulta el siguiente paso para ello.

2. Obtén el código de muestra

Clona el repositorio de GitHub desde la línea de comandos:

git clone https://github.com/firebase/friendlychat

Importa la app de partida

Con tu IDE, abre o importa el directorio android_studio_folder.pngcloud-functions-start desde el directorio del código de muestra. Este directorio contiene el código inicial para el codelab, que consta de una aplicación web de chat completamente funcional.

3. Crea un proyecto de Firebase y configura tu app

Crear proyecto

En Firebase console, haz clic en Agregar proyecto y llámalo FriendlyChat.

Haz clic en Crear proyecto.

Actualiza al plan Blaze

Si quieres usar Cloud Functions para Firebase y Cloud Storage para Firebase, tu proyecto de Firebase debe tener el plan de precios de pago por uso (Blaze), lo que significa que está vinculado a una cuenta de Facturación de Cloud.

  • Una cuenta de Facturación de Cloud requiere una forma de pago, como una tarjeta de crédito.
  • Si es la primera vez que usas Firebase y Google Cloud, verifica si cumples con los requisitos para obtener un crédito de USD 300 y una cuenta de Facturación de Cloud de prueba gratuita.
  • Si realizas este codelab como parte de un evento, pregúntale al organizador si hay créditos de Cloud disponibles.

Si no tienes acceso a una tarjeta de crédito o no te sientes cómodo con el plan de precios de Blaze, considera usar Firebase Emulator Suite, que te permitirá emular Cloud Functions de forma gratuita en tu máquina local.

Todos los proyectos de Firebase, incluidos los del plan de precios Blaze, siguen teniendo acceso a cuotas de uso sin costo para Cloud Functions. Los pasos que se describen en este codelab se encuentran dentro de los límites de uso del nivel gratuito. Sin embargo, verás cargos pequeños (alrededor de USD 0.03) de Cloud Storage, que se usa para alojar las imágenes de compilación de Cloud Functions.

Para actualizar tu proyecto al plan Blaze, sigue estos pasos:

  1. En Firebase console, selecciona la opción para actualizar tu plan.
  2. Selecciona el plan Blaze. Sigue las instrucciones en pantalla para vincular una cuenta de Facturación de Cloud a tu proyecto.
    Si necesitabas crear una cuenta de Facturación de Cloud como parte de esta actualización, es posible que debas volver al flujo de actualización en Firebase console para completarla.

Habilitar la autenticación de Google

Para permitir que los usuarios accedan a la app, usaremos la autenticación de Google, que debe estar habilitada.

En Firebase console, abre la sección Build > Authentication > pestaña Sign-in method (o haz clic aquí para ir allí). Luego, habilita el proveedor de acceso de Google y haz clic en Guardar. Esto permitirá que los usuarios accedan a la aplicación web con sus Cuentas de Google.

Además, no dudes en establecer el nombre público de tu app como Friendly Chat:

8290061806aacb46.png

Configura Cloud Storage para Firebase

La app usa Cloud Storage para subir imágenes.

A continuación, te mostramos cómo configurar Cloud Storage para Firebase en tu proyecto de Firebase:

  1. En el panel izquierdo de Firebase console, expande Compilación y, luego, selecciona Almacenamiento.
  2. Haz clic en Comenzar.
  3. Selecciona una ubicación para tu bucket de Storage predeterminado.
    Los buckets de US-WEST1, US-CENTRAL1 y US-EAST1 pueden aprovechar el nivel “Siempre gratis” de Google Cloud Storage. Los buckets de todas las demás ubicaciones se rigen por los precios y uso de Google Cloud Storage.
  4. Haz clic en Comenzar en modo de prueba. Lee la renuncia de responsabilidad sobre las reglas de seguridad.
    No distribuyas ni expongas una app de forma pública sin agregar reglas de seguridad para el bucket de Storage.
  5. Haz clic en Crear.

Agregar una app web

En Firebase console, agrega una app web. Para ello, ve a Configuración del proyecto y desplázate hacia abajo hasta Agregar app. Elige Web como la plataforma y marca la casilla para configurar Firebase Hosting. Luego, registra la app y haz clic en Siguiente para seguir los pasos restantes y, por último, haz clic en Ir a la consola.

4. Instala la interfaz de línea de comandos de Firebase

La interfaz de línea de comandos (CLI) de Firebase te permitirá publicar la app web a nivel local y, luego, implementar la app web y Cloud Functions.

Para instalar o actualizar la CLI, ejecuta el siguiente comando npm:

npm -g install firebase-tools

Para verificar que la CLI se haya instalado de forma correcta, abre una consola y ejecuta el siguiente comando:

firebase --version

Asegúrate de que la versión de Firebase CLI sea superior a 4.0.0 para que tenga todas las funciones más recientes necesarias para Cloud Functions. De lo contrario, ejecuta npm install -g firebase-tools para actualizar como se muestra más arriba.

Ejecuta el siguiente comando para autorizar Firebase CLI:

firebase login

Asegúrate de estar en el directorio cloud-functions-start y configura Firebase CLI para que use tu proyecto de Firebase:

firebase use --add

Luego, selecciona el ID de tu proyecto y sigue las instrucciones. Cuando se te solicite, puedes elegir cualquier alias, como codelab.

5. Implemente y ejecute la aplicación web

Ahora que importaste y configuraste tu proyecto, tienes todo listo para ejecutar la app web por primera vez. Abre una ventana de terminal, navega a la carpeta cloud-functions-start y, luego, implementa la app web en Firebase Hosting con el siguiente comando:

firebase deploy --except functions

Este es el resultado que debería ver en la consola:

i deploying database, storage, hosting
  database: rules ready to deploy.
i  storage: checking rules for compilation errors...
  storage: rules file compiled successfully
i  hosting: preparing ./ directory for upload...
  hosting: ./ folder uploaded successfully
 storage: rules file compiled successfully
 hosting: 8 files uploaded successfully
i starting release process (may take several minutes)...

 Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlychat-1234/overview
Hosting URL: https://friendlychat-1234.firebaseapp.com

Abrir la app web

La última línea debe mostrar la URL de Hosting. La app web ahora debería entregarse desde esta URL, que debe tener el formato https://<project-id>.firebaseapp.com. Ábrela. Deberías ver la IU en funcionamiento de una app de chat.

Usa el botón ACCEDER CON GOOGLE para acceder a la aplicación y siéntete libre de agregar algunos mensajes y publicar imágenes:

3b1284f5144b54f6.png

Si accedes a la app por primera vez en un navegador nuevo, asegúrate de permitir las notificaciones cuando se te solicite: 8b9d0c66dc36153d.png

Tendremos que habilitar las notificaciones más adelante.

Si hiciste clic en Bloquear por accidente, puedes cambiar este parámetro de configuración. Para ello, haz clic en el botón 🔒 Seguro que está a la izquierda de la URL en la barra multifunción de Chrome y activa la barra junto a Notificaciones:

e926868b0546ed71.png

Ahora, agregaremos algunas funcionalidades con el SDK de Firebase para Cloud Functions.

6. El directorio de Functions

Cloud Functions te permite ejecutar código en la nube sin necesidad de configurar un servidor. Explicaremos cómo compilar funciones que reaccionen a eventos de bases de datos de Firebase Auth, Cloud Storage y Firebase Firestore. Comencemos con la autenticación.

Cuando uses el SDK de Firebase para Cloud Functions, el código de Functions residirá en el directorio functions (de forma predeterminada). El código de Functions también es una app de Node.js y, por lo tanto, necesita un package.json que proporcione información sobre tu app y enumera las dependencias.

Para facilitarte el trabajo, ya creamos el archivo functions/index.js en el que irá tu código. No dudes en inspeccionarlo antes de continuar.

cd functions
ls

Si no estás familiarizado con Node.js, te sería útil obtener más información sobre este antes de continuar con el codelab.

El archivo package.json ya muestra dos dependencias obligatorias: el SDK de Firebase para Cloud Functions y el SDK de Firebase Admin. Para instalarlos de forma local, ve a la carpeta functions y ejecuta lo siguiente:

npm install

A continuación, echemos un vistazo al archivo index.js:

index.js

/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 * ...
 */

// TODO(DEVELOPER): Import the Cloud Functions for Firebase and the Firebase Admin modules here.

// TODO(DEVELOPER): Write the addWelcomeMessage Function here.

// TODO(DEVELOPER): Write the blurImages Function here.

// TODO(DEVELOPER): Write the sendNotification Function here.

Importaremos los módulos necesarios y, luego, escribiremos tres funciones en lugar de los TODO. Comencemos con la importación de los módulos de Node necesarios.

7. Importe los módulos de Cloud Functions y Firebase Admin

Se requerirán dos módulos durante este codelab: firebase-functions permite escribir activadores y registros de Cloud Functions, mientras que firebase-admin permite usar la plataforma de Firebase en un servidor con acceso de administrador para realizar acciones como escribir en Cloud Firestore o enviar notificaciones de FCM.

En el archivo index.js, reemplaza el primer TODO por lo siguiente:

index.js

/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 * ...
 */

// Import the Firebase SDK for Google Cloud Functions.
const functions = require('firebase-functions');
// Import and initialize the Firebase Admin SDK.
const admin = require('firebase-admin');
admin.initializeApp();

// TODO(DEVELOPER): Write the addWelcomeMessage Function here.

// TODO(DEVELOPER): Write the blurImages Function here.

// TODO(DEVELOPER): Write the sendNotification Function here.

El SDK de Firebase Admin se puede configurar automáticamente cuando se implementa en un entorno de Cloud Functions o en otros contenedores de Google Cloud Platform cuando llamamos a admin.initializeApp() sin argumentos.

Ahora, agreguemos una función que se ejecute cuando un usuario acceda por primera vez a la app de chat y agreguemos un mensaje de chat para darle la bienvenida.

8. Deles la bienvenida a los usuarios nuevos

Estructura de los mensajes de chat

Los mensajes que se publican en el feed de chat de FriendlyChat se almacenan en Cloud Firestore. Veamos la estructura de datos que usamos para un mensaje. Para ello, publica un nuevo mensaje en el chat que diga "Hello World":

11f5a676fbb1a69a.png

Debería aparecer de esta manera:

fe6d1c020d0744cf.png

En Firebase console, haz clic en Firestore Database en la sección Compilación. Deberías ver la colección de mensajes y un documento que contiene el mensaje que escribiste:

442c9c10b5e2b245.png

Como puedes ver, los mensajes de chat se almacenan en Cloud Firestore como un documento con los atributos name, profilePicUrl, text y timestamp agregados a la colección messages.

Agrega mensajes de bienvenida

La primera Cloud Function agrega un mensaje de bienvenida al chat a los usuarios nuevos. Para ello, podemos usar el activador functions.auth().onCreate, que ejecuta la función cada vez que un usuario accede por primera vez a la app de Firebase. Agrega la función addWelcomeMessages a tu archivo index.js:

index.js

// Adds a message that welcomes new users into the chat.
exports.addWelcomeMessages = functions.auth.user().onCreate(async (user) => {
  functions.logger.log('A new user signed in for the first time.');
  const fullName = user.displayName || 'Anonymous';

  // Saves the new welcome message into the database
  // which then displays it in the FriendlyChat clients.
  await admin.firestore().collection('messages').add({
    name: 'Firebase Bot',
    profilePicUrl: '/images/firebase-logo.png', // Firebase logo
    text: `${fullName} signed in for the first time! Welcome!`,
    timestamp: admin.firestore.FieldValue.serverTimestamp(),
  });
  functions.logger.log('Welcome message written to database.');
});

Agregar esta función al objeto especial exports es la forma en que Node permite que la función sea accesible fuera del archivo actual, y es necesaria para Cloud Functions.

En la función anterior, agregamos un nuevo mensaje de bienvenida publicado por "Firebase Bot" a la lista de mensajes de chat. Para ello, usamos el método add en la colección messages de Cloud Firestore, que es donde se almacenan los mensajes del chat.

Como se trata de una operación asíncrona, debemos mostrar Promise, que indica cuándo finalizó la escritura de Cloud Firestore para que Cloud Functions no se ejecute demasiado pronto.

Implementa Cloud Functions con los siguientes comandos:

Cloud Functions solo estará activa después de que la implementes. Para ello, ejecuta lo siguiente en la línea de comandos:

firebase deploy --only functions

Este es el resultado que debería ver en la consola:

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
  functions: missing necessary APIs. Enabling now...
i  env: ensuring necessary APIs are enabled...
  env: missing necessary APIs. Enabling now...
i  functions: waiting for APIs to activate...
i  env: waiting for APIs to activate...
  env: all necessary APIs are enabled
  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (X.XX KB) for uploading
  functions: functions folder uploaded successfully
i  starting release process (may take several minutes)...
i  functions: creating function addWelcomeMessages...
  functions[addWelcomeMessages]: Successful create operation. 
  functions: all functions deployed successfully!

  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlypchat-1234/overview

Prueba la función

Cuando la función se haya implementado correctamente, necesitarás un usuario que acceda por primera vez.

  1. Abre la app en el navegador con la URL de hosting (en el formato de https://<project-id>.firebaseapp.com).
  2. Con un usuario nuevo, accede por primera vez a tu app con el botón Acceder.

262535d1b1223c65.png

  1. Después de acceder, debería mostrarse automáticamente un mensaje de bienvenida:

1c70e0d64b23525b.png

9. Moderación de imágenes

Los usuarios pueden subir todo tipo de imágenes al chat, y siempre es importante moderar las imágenes ofensivas, sobre todo en plataformas sociales públicas. En FRIENDChat, las imágenes que se publican en el chat se almacenan en buckets de Cloud Storage.

Con Cloud Functions, puedes detectar nuevas cargas de imágenes con el activador functions.storage().onFinalize. Este activador se ejecutará cada vez que se suba un archivo nuevo a Cloud Storage o se modifique.

Para moderar las imágenes, tenemos que seguir el siguiente proceso:

  1. Utilice la API de Cloud Vision a fin de comprobar si la imagen se marcó como contenido violento o para adultos.
  2. Si la imagen se marcó, descárgala en la instancia de Functions en ejecución.
  3. Use ImageMagick para desenfocar la imagen.
  4. Suba la imagen desenfocada a Cloud Storage.

Habilite la API de Cloud Vision

Dado que usaremos la API de Google Cloud Vision en esta función, debes habilitar la API en tu proyecto de Firebase. Sigue este vínculo. Luego, selecciona tu proyecto de Firebase y habilita la API:

5c77fee51ec5de49.png

Instala dependencias

Para moderar las imágenes, usaremos @google-cloud/vision, la biblioteca cliente de Google Cloud Vision para Node.js, a fin de ejecutar imágenes con la API de Cloud Vision y detectar imágenes inapropiadas.

Para instalar este paquete en tu app de Cloud Functions, ejecuta el siguiente comando npm install --save. Asegúrate de hacerlo desde el directorio functions.

npm install --save @google-cloud/vision@2.4.0

Esto instalará el paquete de forma local y los agregará como dependencia declarada en tu archivo package.json.

Importa y configura dependencias

Para importar las dependencias que se instalaron y algunos módulos principales de Node.js (path, os y fs) que necesitaremos en esta sección, agrega las siguientes líneas a la parte superior de tu archivo index.js:

index.js

const Vision = require('@google-cloud/vision');
const vision = new Vision.ImageAnnotatorClient();
const {promisify} = require('util');
const exec = promisify(require('child_process').exec);

const path = require('path');
const os = require('os');
const fs = require('fs');

Dado que tu función se ejecutará dentro de un entorno de Google Cloud, no es necesario configurar las bibliotecas de Cloud Storage y Cloud Vision: se configurarán automáticamente para usar tu proyecto.

Detecta imágenes inapropiadas

Usarás el activador functions.storage.onChange de Cloud Functions, que ejecutará tu código en cuanto se cree o modifique un archivo o una carpeta en un bucket de Cloud Storage. Agrega la función blurOffensiveImages a tu archivo index.js:

index.js

// Checks if uploaded images are flagged as Adult or Violence and if so blurs them.
exports.blurOffensiveImages = functions.runWith({memory: '2GB'}).storage.object().onFinalize(
    async (object) => {
      const imageUri = `gs://${object.bucket}/${object.name}`;
      // Check the image content using the Cloud Vision API.
      const batchAnnotateImagesResponse = await vision.safeSearchDetection(imageUri);
      const safeSearchResult = batchAnnotateImagesResponse[0].safeSearchAnnotation;
      const Likelihood = Vision.protos.google.cloud.vision.v1.Likelihood;
      if (Likelihood[safeSearchResult.adult] >= Likelihood.LIKELY ||
          Likelihood[safeSearchResult.violence] >= Likelihood.LIKELY) {
        functions.logger.log('The image', object.name, 'has been detected as inappropriate.');
        return blurImage(object.name);
      }
      functions.logger.log('The image', object.name, 'has been detected as OK.');
    });

Ten en cuenta que agregamos algunos parámetros de configuración de la instancia de Cloud Functions que ejecutará la función. Con .runWith({memory: '2GB'}), solicitamos que la instancia obtenga 2 GB de memoria en lugar de la cantidad predeterminada, ya que esta función consume mucha memoria.

Cuando se activa la función, la imagen se analiza por la API de Cloud Vision para detectar si se marca como contenido violento o para adultos. Si la imagen se detecta como inapropiada en función de estos criterios, la desenfocamos, lo que se hace en la función blurImage, como veremos a continuación.

Desenfoca la imagen

Agrega la siguiente función blurImage al archivo index.js:

index.js

// Blurs the given image located in the given bucket using ImageMagick.
async function blurImage(filePath) {
  const tempLocalFile = path.join(os.tmpdir(), path.basename(filePath));
  const messageId = filePath.split(path.sep)[1];
  const bucket = admin.storage().bucket();

  // Download file from bucket.
  await bucket.file(filePath).download({destination: tempLocalFile});
  functions.logger.log('Image has been downloaded to', tempLocalFile);
  // Blur the image using ImageMagick.
  await exec(`convert "${tempLocalFile}" -channel RGBA -blur 0x24 "${tempLocalFile}"`);
  functions.logger.log('Image has been blurred');
  // Uploading the Blurred image back into the bucket.
  await bucket.upload(tempLocalFile, {destination: filePath});
  functions.logger.log('Blurred image has been uploaded to', filePath);
  // Deleting the local file to free up disk space.
  fs.unlinkSync(tempLocalFile);
  functions.logger.log('Deleted local file.');
  // Indicate that the message has been moderated.
  await admin.firestore().collection('messages').doc(messageId).update({moderated: true});
  functions.logger.log('Marked the image as moderated in the database.');
}

En la función anterior, el objeto binario de imagen se descarga desde Cloud Storage. Luego, la imagen se desenfoca con la herramienta convert de ImageMagick, y la versión desenfocada se vuelve a subir al bucket de Storage. A continuación, borramos el archivo de la instancia de Cloud Functions para liberar espacio en el disco. Esto se hace porque la misma instancia de Cloud Functions se puede volver a usar y, si los archivos no se limpian, podría quedarse sin espacio en el disco. Por último, agregamos un valor booleano al mensaje de chat, que indica que la imagen se moderó, lo que activará una actualización del mensaje en el cliente.

Implementa la función

La función solo estará activa después de que la hayas implementado. En la línea de comandos, ejecuta firebase deploy --only functions:

firebase deploy --only functions

Este es el resultado que debería ver en la consola:

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (X.XX KB) for uploading
  functions: functions folder uploaded successfully
i  starting release process (may take several minutes)...
i  functions: updating function addWelcomeMessages...
i  functions: creating function blurOffensiveImages...
  functions[addWelcomeMessages]: Successful update operation.
  functions[blurOffensiveImages]: Successful create operation.
  functions: all functions deployed successfully!

  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlychat-1234/overview

Prueba la función

Cuando la función se haya implementado correctamente, siga estos pasos:

  1. Abre la app en tu navegador con la URL de hosting (en forma de https://<project-id>.firebaseapp.com).
  2. Una vez que accedas a la app, sube una imagen: 4db9fdab56703e4a.png
  3. Elige la mejor imagen ofensiva para subirla (o puedes usar la de este zombi que come carne humana). Después de unos momentos, deberías ver que tu publicación se actualiza con una versión desenfocada de la imagen: 83dd904fbaf97d2b.png

10. Notificaciones de mensajes nuevos

En esta sección, agregarás una Cloud Function que envíe notificaciones a los participantes del chat cuando se publique un mensaje nuevo.

Con Firebase Cloud Messaging (FCM), puedes enviar notificaciones a los usuarios en diferentes plataformas de manera confiable. Para enviar una notificación a un usuario, necesitas su token de dispositivo de FCM. La aplicación web de chat que estamos usando ya recopila tokens de dispositivo de los usuarios cuando estos abren la aplicación por primera vez en un navegador o dispositivo nuevos. Estos tokens se almacenan en Cloud Firestore, en la colección fcmTokens.

Si quieres obtener información para obtener tokens de dispositivo de FCM en una app web, puedes consultar el codelab de Firebase Web.

Cómo enviar notificaciones

Para detectar cuándo se publican mensajes nuevos, usará el activador functions.firestore.document().onCreate de Cloud Functions, que ejecuta tu código cuando se crea un objeto nuevo en una determinada ruta de Cloud Firestore. Agrega la función sendNotifications a tu archivo index.js:

index.js

// Sends a notifications to all users when a new message is posted.
exports.sendNotifications = functions.firestore.document('messages/{messageId}').onCreate(
  async (snapshot) => {
    // Notification details.
    const text = snapshot.data().text;
    const payload = {
      notification: {
        title: `${snapshot.data().name} posted ${text ? 'a message' : 'an image'}`,
        body: text ? (text.length <= 100 ? text : text.substring(0, 97) + '...') : '',
        icon: snapshot.data().profilePicUrl || '/images/profile_placeholder.png',
        click_action: `https://${process.env.GCLOUD_PROJECT}.firebaseapp.com`,
      }
    };

    // Get the list of device tokens.
    const allTokens = await admin.firestore().collection('fcmTokens').get();
    const tokens = [];
    allTokens.forEach((tokenDoc) => {
      tokens.push(tokenDoc.id);
    });

    if (tokens.length > 0) {
      // Send notifications to all tokens.
      const response = await admin.messaging().sendToDevice(tokens, payload);
      await cleanupTokens(response, tokens);
      functions.logger.log('Notifications have been sent and tokens cleaned up.');
    }
  });

En la función anterior, recopilamos los tokens de dispositivo de todos los usuarios de la base de datos de Cloud Firestore y les enviamos una notificación a cada uno de ellos con la función admin.messaging().sendToDevice.

Limpia los tokens

Por último, queremos quitar los tokens que ya no son válidos. Esto sucede cuando el navegador o el dispositivo ya no utilizan el token que recibimos del usuario. Por ejemplo, esto sucede si el usuario revocó el permiso de notificaciones para la sesión del navegador. Para ello, agrega la siguiente función cleanupTokens a tu archivo index.js:

index.js

// Cleans up the tokens that are no longer valid.
function cleanupTokens(response, tokens) {
 // For each notification we check if there was an error.
 const tokensDelete = [];
 response.results.forEach((result, index) => {
   const error = result.error;
   if (error) {
     functions.logger.error('Failure sending notification to', tokens[index], error);
     // Cleanup the tokens that are not registered anymore.
     if (error.code === 'messaging/invalid-registration-token' ||
         error.code === 'messaging/registration-token-not-registered') {
       const deleteTask = admin.firestore().collection('fcmTokens').doc(tokens[index]).delete();
       tokensDelete.push(deleteTask);
     }
   }
 });
 return Promise.all(tokensDelete);
}

Implementa la función

La función solo estará activa después de que la implementes. Para ello, ejecuta el siguiente comando en la línea de comandos:

firebase deploy --only functions

Este es el resultado que debería ver en la consola:

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (X.XX KB) for uploading
  functions: functions folder uploaded successfully
i  starting release process (may take several minutes)...
i  functions: updating function addWelcomeMessages...
i  functions: updating function blurOffensiveImages...
i  functions: creating function sendNotifications...
  functions[addWelcomeMessages]: Successful update operation.
  functions[blurOffensiveImages]: Successful updating operation.
  functions[sendNotifications]: Successful create operation.
  functions: all functions deployed successfully!

  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlychat-1234/overview

Prueba la función

  1. Una vez que se haya implementado correctamente la función, abre la app en tu navegador mediante la URL de hosting (en el formato de https://<project-id>.firebaseapp.com).
  2. Si accedes a la app por primera vez, asegúrate de permitir las notificaciones cuando se te solicite: 8b9d0c66dc36153d.png
  3. Cierra la pestaña de la aplicación de chat o muestra una pestaña diferente: Las notificaciones solo aparecen si la app está en segundo plano. Si deseas obtener información para recibir mensajes mientras la app está en primer plano, consulta nuestra documentación.
  4. Usa otro navegador (o una ventana de incógnito), accede a la app y publica un mensaje. El primer navegador debería mostrar una notificación: 45282ab12b28b926.png

11. ¡Felicitaciones!

Utilizó el SDK de Firebase para Cloud Functions y agregó componentes del lado del servidor a una aplicación de chat.

Temas abordados

  • Cómo crear funciones de Cloud Functions con el SDK de Firebase para Cloud Functions
  • Cómo activar funciones de Cloud Functions basadas en eventos de Auth, Cloud Storage y Cloud Firestore
  • Cómo agregar compatibilidad con Firebase Cloud Messaging a su aplicación web
  • Implementa Cloud Functions con Firebase CLI.

Próximos pasos

Más información