Senden Sie Benachrichtigungen für eine Web-App mit Cloud Messaging und Cloud Functions

Mit Sammlungen den Überblick behalten Sie können Inhalte basierend auf Ihren Einstellungen speichern und kategorisieren.

1. Übersicht

In diesem Codelab erfahren Sie, wie Sie mit Cloud Functions for Firebase Funktionen zu einer Chat-Web-App hinzufügen, indem Sie Benachrichtigungen an Benutzer der Chat-App senden.

3b1284f5144b54f6.png

Was Sie lernen werden

  • Erstellen Sie Google Cloud Functions mit dem Firebase SDK.
  • Lösen Sie Cloud Functions basierend auf Auth-, Cloud Storage- und Cloud Firestore-Ereignissen aus.
  • Fügen Sie Ihrer Web-App Firebase Cloud Messaging-Unterstützung hinzu.

Was du brauchen wirst

  • Eine Kreditkarte. Cloud Functions for Firebase erfordert den Firebase Blaze-Plan, was bedeutet, dass Sie die Abrechnung für Ihr Firebase-Projekt mit einer Kreditkarte aktivieren müssen.
  • Die IDE/Text-Editor Ihrer Wahl wie WebStorm , Atom oder Sublime .
  • Ein Terminal zum Ausführen von Shell-Befehlen mit installiertem NodeJS v9.
  • Ein Browser wie Chrome.
  • Der Beispielcode. Siehe dazu den nächsten Schritt.

2. Holen Sie sich den Beispielcode

Klonen Sie das GitHub-Repository über die Befehlszeile:

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

Importieren Sie die Starter-App

Öffnen oder importieren Sie mit Ihrer IDE die android_studio_folder.png cloud-functions-start Verzeichnis aus dem Beispielcodeverzeichnis. Dieses Verzeichnis enthält den Startcode für das Codelab, das aus einer voll funktionsfähigen Chat-Web-App besteht.

3. Erstellen Sie ein Firebase-Projekt und richten Sie Ihre App ein

Projekt erstellen

Klicken Sie in der Firebase Console auf Projekt hinzufügen und nennen Sie es FriendlyChat .

Klicken Sie auf Projekt erstellen .

Upgrade auf den Blaze-Plan

Um Cloud Functions for Firebase verwenden zu können, müssen Sie Ihr Firebase-Projekt auf den Blaze-Abrechnungsplan aktualisieren . Dazu müssen Sie Ihrem Google Cloud-Konto eine Kreditkarte oder ein anderes Abrechnungsinstrument hinzufügen.

Alle Firebase-Projekte, einschließlich derjenigen im Blaze-Plan, haben weiterhin Zugriff auf die kostenlosen Nutzungskontingente für Cloud Functions. Die in diesem Codelab beschriebenen Schritte fallen unter die Nutzungsbeschränkungen des kostenlosen Kontingents. Es fallen jedoch geringe Gebühren ( ca. 0,03 $ ) von Cloud Storage an, das zum Hosten Ihrer Cloud Functions-Build-Images verwendet wird.

Wenn Sie keinen Zugriff auf eine Kreditkarte haben oder den Blaze-Plan nicht fortsetzen möchten, sollten Sie die Firebase Emulator Suite verwenden, mit der Sie Cloud-Funktionen kostenlos auf Ihrem lokalen Computer emulieren können.

Aktivieren Sie Google Auth

Damit sich Benutzer in der App anmelden können, verwenden wir die Google-Authentifizierung, die aktiviert sein muss.

Öffnen Sie in der Firebase-Konsole den Abschnitt Erstellen > Authentifizierung > Registerkarte Anmeldemethode (oder klicken Sie hier, um dorthin zu gelangen). Aktivieren Sie dann den Google -Anmeldeanbieter und klicken Sie auf Speichern . Dadurch können sich Benutzer mit ihren Google-Konten in der Web-App anmelden.

Sie können auch den öffentlich zugänglichen Namen Ihrer App auf Friendly Chat festlegen:

8290061806aacb46.png

Cloud-Speicher aktivieren

Die App verwendet Cloud Storage, um Bilder hochzuladen. Um Cloud Storage für Ihr Firebase-Projekt zu aktivieren, besuchen Sie den Abschnitt „Storage “ und klicken Sie auf die Schaltfläche „Erste Schritte“ . Gehen Sie dort die Schritte durch, und für den Cloud-Speicherort gibt es einen zu verwendenden Standardwert. Klicken Sie anschließend auf Fertig .

Fügen Sie eine Web-App hinzu

Fügen Sie in der Firebase Console eine Web-App hinzu. Gehen Sie dazu zu den Projekteinstellungen und scrollen Sie nach unten zu App hinzufügen . Wählen Sie Web als Plattform und aktivieren Sie das Kontrollkästchen zum Einrichten von Firebase Hosting, registrieren Sie dann die App und klicken Sie für die restlichen Schritte auf Weiter , und klicken Sie zuletzt auf Weiter zur Konsole .

4. Installieren Sie die Firebase-Befehlszeilenschnittstelle

Mit der Firebase-Befehlszeilenschnittstelle (CLI) können Sie die Web-App lokal bereitstellen und Ihre Web-App und Cloud-Funktionen bereitstellen.

Um die CLI zu installieren oder zu aktualisieren, führen Sie den folgenden npm-Befehl aus:

npm -g install firebase-tools

Um zu überprüfen, ob die CLI korrekt installiert wurde, öffnen Sie eine Konsole und führen Sie Folgendes aus:

firebase --version

Stellen Sie sicher, dass die Version der Firebase CLI höher als 4.0.0 ist, damit sie über alle aktuellen Funktionen verfügt, die für Cloud Functions erforderlich sind. Wenn nicht, führen Sie npm install -g firebase-tools aus, um wie oben gezeigt zu aktualisieren.

Autorisieren Sie die Firebase CLI, indem Sie Folgendes ausführen:

firebase login

Stellen Sie sicher, dass Sie sich im Verzeichnis cloud-functions-start befinden, und richten Sie dann die Firebase-CLI für die Verwendung Ihres Firebase-Projekts ein:

firebase use --add

Wählen Sie als Nächstes Ihre Projekt-ID aus und folgen Sie den Anweisungen. Wenn Sie dazu aufgefordert werden, können Sie einen beliebigen Alias ​​auswählen, z. B. codelab .

5. Stellen Sie die Web-App bereit und führen Sie sie aus

Nachdem Sie Ihr Projekt importiert und konfiguriert haben, können Sie die Web-App zum ersten Mal ausführen! Öffnen Sie ein Terminalfenster, navigieren Sie zum Ordner cloud-functions-start und stellen Sie die Web-App für das Firebase-Hosting bereit:

firebase deploy --except functions

Dies ist die Konsolenausgabe, die Sie sehen sollten:

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

Öffnen Sie die Web-App

Die letzte Zeile sollte die Hosting-URL anzeigen. Die Web-App sollte jetzt von dieser URL bereitgestellt werden, die das Format https://<Projekt-ID>.firebaseapp.com haben sollte. Öffne es. Sie sollten die funktionierende Benutzeroberfläche einer Chat-App sehen.

Melden Sie sich über die Schaltfläche MIT GOOGLE ANMELDEN in der App an und fügen Sie gerne einige Nachrichten hinzu und posten Sie Bilder:

3b1284f5144b54f6.png

Wenn Sie sich zum ersten Mal in einem neuen Browser bei der App anmelden, vergewissern Sie sich, dass Sie Benachrichtigungen zulassen, wenn Sie dazu aufgefordert werden: 8b9d0c66dc36153d.png

Wir müssen Benachrichtigungen zu einem späteren Zeitpunkt aktivieren.

Wenn Sie versehentlich auf Blockieren geklickt haben, können Sie diese Einstellung ändern, indem Sie auf die Schaltfläche 🔒 Sicher links neben der URL in der Chrome Omnibar klicken und die Leiste neben Benachrichtigungen umschalten:

e926868b0546ed71.png

Jetzt fügen wir mithilfe des Firebase SDK for Cloud Functions einige Funktionen hinzu.

6. Das Funktionsverzeichnis

Mit Cloud Functions können Sie ganz einfach Code haben, der in der Cloud ausgeführt wird, ohne dass Sie einen Server einrichten müssen. Wir werden durchgehen, wie Funktionen erstellt werden, die auf Firebase Auth-, Cloud Storage- und Firebase Firestore-Datenbankereignisse reagieren. Beginnen wir mit Auth.

Wenn Sie das Firebase SDK für Cloud Functions verwenden, befindet sich Ihr Functions-Code (standardmäßig) im functions . Ihr Functions-Code ist auch eine Node.js- App und benötigt daher eine package.json , die einige Informationen über Ihre App enthält und Abhängigkeiten auflistet.

Um es Ihnen einfacher zu machen, haben wir bereits die Datei functions/index.js erstellt, in der Ihr Code abgelegt wird. Fühlen Sie sich frei, diese Datei zu überprüfen, bevor Sie fortfahren.

cd functions
ls

Wenn Sie mit Node.js nicht vertraut sind, wäre es hilfreich, mehr darüber zu erfahren, bevor Sie mit dem Codelab fortfahren.

Die Datei package.json listet bereits zwei erforderliche Abhängigkeiten auf: das Firebase SDK für Cloud Functions und das Firebase Admin SDK . Um sie lokal zu installieren, gehen Sie in den functions und führen Sie Folgendes aus:

npm install

Schauen wir uns nun die Datei index.js an:

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.

Wir importieren die erforderlichen Module und schreiben dann drei Funktionen anstelle der TODOs. Beginnen wir mit dem Importieren der erforderlichen Node-Module.

7. Importieren Sie die Module Cloud Functions und Firebase Admin

Während dieses Codelabs sind zwei Module erforderlich: firebase-functions ermöglicht das Schreiben von Cloud Functions-Triggern und -Protokollen, während firebase-admin die Verwendung der Firebase-Plattform auf einem Server mit Administratorzugriff ermöglicht, um Aktionen wie das Schreiben in Cloud Firestore oder das Senden von FCM-Benachrichtigungen auszuführen.

Ersetzen Sie in der Datei index.js das erste TODO durch Folgendes:

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.

Das Firebase Admin SDK kann automatisch konfiguriert werden, wenn es in einer Cloud Functions-Umgebung oder anderen Google Cloud Platform-Containern bereitgestellt wird, und dies geschieht, wenn wir admin.initializeApp() ohne Argumente aufrufen.

Lassen Sie uns nun eine Funktion hinzufügen, die ausgeführt wird, wenn sich ein Benutzer zum ersten Mal in der Chat-App anmeldet, und wir fügen eine Chatnachricht hinzu, um den Benutzer willkommen zu heißen.

8. Neue Benutzer willkommen heißen

Struktur von Chat-Nachrichten

Im FriendlyChat-Chat-Feed gepostete Nachrichten werden in Cloud Firestore gespeichert. Schauen wir uns die Datenstruktur an, die wir für eine Nachricht verwenden. Posten Sie dazu eine neue Nachricht im Chat mit der Aufschrift „Hello World“:

11f5a676fbb1a69a.png

Dies sollte folgendermaßen aussehen:

fe6d1c020d0744cf.png

Klicken Sie in der Firebase-Konsole im Abschnitt „Erstellen“ auf „Firestore-Datenbank“ . Sie sollten die Nachrichtensammlung und ein Dokument mit der von Ihnen geschriebenen Nachricht sehen:

442c9c10b5e2b245.png

Wie Sie sehen können, werden Chatnachrichten in Cloud Firestore als Dokument gespeichert, wobei die Attribute name , profilePicUrl , text und timestamp der messages hinzugefügt werden.

Begrüßungsnachrichten hinzufügen

Die erste Cloud-Funktion fügt eine Nachricht hinzu, die neue Benutzer im Chat willkommen heißt. Dazu können wir den Trigger functions.auth().onCreate verwenden, der die Funktion jedes Mal ausführt, wenn sich ein Benutzer zum ersten Mal in der Firebase-App anmeldet. Fügen Sie die addWelcomeMessages -Funktion in Ihre index.js Datei ein:

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.');
});

Das Hinzufügen dieser Funktion zum speziellen exports Objekt ist die Art und Weise, wie Node die Funktion außerhalb der aktuellen Datei zugänglich macht, und ist für Cloud-Funktionen erforderlich.

In der obigen Funktion fügen wir der Liste der Chatnachrichten eine neue Willkommensnachricht hinzu, die von „Firebase Bot“ gepostet wurde. Wir tun dies, indem wir die add Methode für die messages in Cloud Firestore verwenden, wo die Nachrichten des Chats gespeichert werden.

Da dies ein asynchroner Vorgang ist, müssen wir das Promise zurückgeben, das angibt, wann Cloud Firestore mit dem Schreiben fertig ist, damit die Cloud Functions nicht zu früh ausgeführt werden.

Cloud-Funktionen bereitstellen

Cloud Functions sind erst aktiv, nachdem Sie sie bereitgestellt haben. Führen Sie dazu dies in der Befehlszeile aus:

firebase deploy --only functions

Dies ist die Konsolenausgabe, die Sie sehen sollten:

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

Testen Sie die Funktion

Sobald die Funktion erfolgreich bereitgestellt wurde, benötigen Sie einen Benutzer, der sich zum ersten Mal anmeldet.

  1. Öffnen Sie Ihre App in Ihrem Browser mit der Hosting-URL (in Form von https://<project-id>.firebaseapp.com ).
  2. Als neuer Benutzer melden Sie sich zum ersten Mal in Ihrer App über die Schaltfläche Anmelden an.
  • Wenn Sie sich bereits bei der App angemeldet haben, können Sie die Firebase Console-Authentifizierung öffnen und Ihr Konto aus der Benutzerliste löschen. Melden Sie sich dann erneut an.

262535d1b1223c65.png

  1. Nachdem Sie sich angemeldet haben, sollte automatisch eine Willkommensnachricht angezeigt werden:

1c70e0d64b23525b.png

9. Bildmoderation

Benutzer können alle Arten von Bildern in den Chat hochladen, und es ist immer wichtig, anstößige Bilder zu moderieren, insbesondere auf öffentlichen sozialen Plattformen. In FriendlyChat werden die Bilder, die im Chat veröffentlicht werden, in Google Cloud Storage gespeichert.

Mit Cloud Functions können Sie neue Bilduploads mit dem Trigger functions.storage().onFinalize erkennen. Dies wird jedes Mal ausgeführt, wenn eine neue Datei in Cloud Storage hochgeladen oder geändert wird.

Um Bilder zu moderieren, durchlaufen wir den folgenden Prozess:

  1. Überprüfen Sie mithilfe der Cloud Vision API , ob das Bild als nicht jugendfrei oder gewalttätig gekennzeichnet ist.
  2. Wenn das Image gekennzeichnet wurde, laden Sie es auf die ausgeführte Functions-Instanz herunter.
  3. Verwischen Sie das Bild mit ImageMagick .
  4. Laden Sie das unscharfe Bild in Cloud Storage hoch.

Aktivieren Sie die Cloud Vision-API

Da wir in dieser Funktion die Google Cloud Vision-API verwenden, müssen Sie die API in Ihrem Firebase-Projekt aktivieren. Folgen Sie diesem Link , wählen Sie dann Ihr Firebase-Projekt aus und aktivieren Sie die API:

5c77fee51ec5de49.png

Abhängigkeiten installieren

Um Bilder zu moderieren, verwenden wir die Google Cloud Vision-Clientbibliothek für Node.js, @google-cloud/vision , um Bilder über die Cloud Vision-API auszuführen, um unangemessene Bilder zu erkennen.

Um dieses Paket in Ihrer Cloud Functions-App zu installieren, führen Sie den folgenden Befehl npm install --save aus. Stellen Sie sicher, dass Sie dies vom functions aus tun.

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

Dadurch wird das Paket lokal installiert und als deklarierte Abhängigkeit in Ihrer Datei package.json hinzugefügt.

Abhängigkeiten importieren und konfigurieren

Um die installierten Abhängigkeiten und einige Node.js-Kernmodule ( path , os und fs ) zu importieren, die wir in diesem Abschnitt benötigen, fügen Sie die folgenden Zeilen am Anfang Ihrer index.js -Datei hinzu:

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');

Da Ihre Funktion in einer Google Cloud-Umgebung ausgeführt wird, müssen die Cloud Storage- und Cloud Vision-Bibliotheken nicht konfiguriert werden: Sie werden automatisch für die Verwendung Ihres Projekts konfiguriert.

Unangemessene Bilder erkennen

Sie verwenden den Cloud Functions-Trigger functions.storage.onChange , der Ihren Code ausführt, sobald eine Datei oder ein Ordner in einem Cloud Storage-Bucket erstellt oder geändert wird. Fügen Sie die blurOffensiveImages -Funktion in Ihre index.js Datei ein:

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.');
    });

Beachten Sie, dass wir eine Konfiguration der Cloud Functions-Instanz hinzugefügt haben, die die Funktion ausführt. Mit .runWith({memory: '2GB'}) fordern wir an, dass die Instanz 2 GB Arbeitsspeicher anstelle des Standardwerts erhält, da diese Funktion speicherintensiv ist.

Wenn die Funktion ausgelöst wird, wird das Bild durch die Cloud Vision API geleitet, um zu erkennen, ob es als nicht jugendfrei oder gewalttätig gekennzeichnet ist. Wenn das Bild basierend auf diesen Kriterien als unangemessen erkannt wird, verwischen wir das Bild, was in der Funktion blurImage erfolgt, wie wir als Nächstes sehen werden.

Verwischen des Bildes

Fügen Sie Ihrer index.js Datei die folgende blurImage Funktion hinzu:

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.');
}

In der obigen Funktion wird die Bildbinärdatei von Cloud Storage heruntergeladen. Das Bild wird dann mit dem convert von ImageMagick unkenntlich gemacht, und die unkenntlich gemachte Version wird erneut in den Storage Bucket hochgeladen. Als Nächstes löschen wir die Datei auf der Cloud Functions-Instanz, um etwas Speicherplatz freizugeben, und zwar, weil dieselbe Cloud Functions-Instanz wiederverwendet werden kann und wenn Dateien nicht bereinigt werden, könnte ihr Speicherplatz ausgehen. Schließlich fügen wir der Chat-Nachricht einen booleschen Wert hinzu, der angibt, dass das Bild moderiert wurde, und dies löst eine Aktualisierung der Nachricht auf dem Client aus.

Stellen Sie die Funktion bereit

Die Funktion ist erst aktiv, nachdem Sie sie bereitgestellt haben. Führen Sie in der Befehlszeile firebase deploy --only functions aus:

firebase deploy --only functions

Dies ist die Konsolenausgabe, die Sie sehen sollten:

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

Testen Sie die Funktion

Nach erfolgreicher Bereitstellung der Funktion:

  1. Öffnen Sie Ihre App in Ihrem Browser mit der Hosting-URL (in Form von https://<project-id>.firebaseapp.com ).
  2. Sobald Sie sich bei der App angemeldet haben, laden Sie ein Bild hoch: 4db9fdab56703e4a.png
  3. Wählen Sie Ihr bestes anstößiges Bild zum Hochladen (oder Sie können diesen fleischfressenden Zombie verwenden!) und nach ein paar Augenblicken sollte Ihr Beitrag mit einer unscharfen Version des Bildes aktualisiert werden: 83dd904fbaf97d2b.png

10. Benachrichtigungen über neue Nachrichten

In diesem Abschnitt fügen Sie eine Cloud-Funktion hinzu, die Benachrichtigungen an die Teilnehmer des Chats sendet, wenn eine neue Nachricht gepostet wird.

Mit Firebase Cloud Messaging (FCM) können Sie plattformübergreifend zuverlässig Benachrichtigungen an Benutzer senden. Um eine Benachrichtigung an einen Benutzer zu senden, benötigen Sie dessen FCM-Gerätetoken. Die von uns verwendete Chat-Web-App sammelt bereits Geräte-Token von Benutzern, wenn sie die App zum ersten Mal auf einem neuen Browser oder Gerät öffnen. Diese Token werden in Cloud Firestore in der fcmTokens Sammlung gespeichert.

Wenn Sie erfahren möchten, wie Sie FCM-Gerätetoken in einer Web-App erhalten, können Sie das Firebase Web Codelab durchgehen.

Benachrichtigungen senden

Um zu erkennen, wann neue Nachrichten gepostet werden, verwenden Sie den Trigger functions.firestore.document().onCreate Cloud Functions, der Ihren Code ausführt, wenn ein neues Objekt in einem bestimmten Pfad von Cloud Firestore erstellt wird. Fügen Sie die sendNotifications -Funktion in Ihre index.js Datei ein:

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.');
    }
  });

In der obigen Funktion sammeln wir die Gerätetoken aller Benutzer aus der Cloud Firestore-Datenbank und senden mit der Funktion admin.messaging().sendToDevice eine Benachrichtigung an jeden von ihnen.

Bereinigen Sie die Token

Schließlich wollen wir die Token entfernen, die nicht mehr gültig sind. Dies geschieht, wenn das Token, das wir einmal vom Benutzer erhalten haben, nicht mehr vom Browser oder Gerät verwendet wird. Dies ist beispielsweise der Fall, wenn der Benutzer die Benachrichtigungserlaubnis für die Browsersitzung widerrufen hat. Fügen Sie dazu die folgende cleanupTokens Funktion in Ihre index.js Datei ein:

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);
}

Stellen Sie die Funktion bereit

Die Funktion ist erst aktiv, nachdem Sie sie bereitgestellt haben, und um sie bereitzustellen, führen Sie Folgendes in der Befehlszeile aus:

firebase deploy --only functions

Dies ist die Konsolenausgabe, die Sie sehen sollten:

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

Testen Sie die Funktion

  1. Sobald die Funktion erfolgreich bereitgestellt wurde, öffnen Sie Ihre App in Ihrem Browser mit der Hosting-URL (in der Form https://<project-id>.firebaseapp.com ).
  2. Wenn Sie sich zum ersten Mal in der App anmelden, stellen Sie sicher, dass Sie Benachrichtigungen zulassen, wenn Sie dazu aufgefordert werden: 8b9d0c66dc36153d.png
  3. Schließen Sie die Registerkarte der Chat-App oder zeigen Sie eine andere Registerkarte an: Benachrichtigungen werden nur angezeigt, wenn sich die App im Hintergrund befindet. Wenn Sie erfahren möchten, wie Sie Nachrichten empfangen, während Ihre App im Vordergrund ist, werfen Sie einen Blick in unsere Dokumentation .
  4. Melden Sie sich mit einem anderen Browser (oder einem Inkognito-Fenster) bei der App an und posten Sie eine Nachricht. Sie sollten eine Benachrichtigung sehen, die vom ersten Browser angezeigt wird: 45282ab12b28b926.png

11. Herzlichen Glückwunsch!

Sie haben das Firebase SDK for Cloud Functions verwendet und einer Chat-App serverseitige Komponenten hinzugefügt.

Was wir abgedeckt haben

  • Erstellen von Cloud-Funktionen mit dem Firebase SDK für Cloud-Funktionen.
  • Lösen Sie Cloud Functions basierend auf Auth-, Cloud Storage- und Cloud Firestore-Ereignissen aus.
  • Fügen Sie Ihrer Web-App Firebase Cloud Messaging-Unterstützung hinzu.
  • Stellen Sie Cloud Functions mithilfe der Firebase-Befehlszeilenschnittstelle bereit.

Nächste Schritte

Erfahren Sie mehr

,

1. Übersicht

In diesem Codelab erfahren Sie, wie Sie mit Cloud Functions for Firebase Funktionen zu einer Chat-Web-App hinzufügen, indem Sie Benachrichtigungen an Benutzer der Chat-App senden.

3b1284f5144b54f6.png

Was Sie lernen werden

  • Erstellen Sie Google Cloud Functions mit dem Firebase SDK.
  • Lösen Sie Cloud Functions basierend auf Auth-, Cloud Storage- und Cloud Firestore-Ereignissen aus.
  • Fügen Sie Ihrer Web-App Firebase Cloud Messaging-Unterstützung hinzu.

Was du brauchen wirst

  • Eine Kreditkarte. Cloud Functions for Firebase erfordert den Firebase Blaze-Plan, was bedeutet, dass Sie die Abrechnung für Ihr Firebase-Projekt mit einer Kreditkarte aktivieren müssen.
  • Die IDE/Text-Editor Ihrer Wahl wie WebStorm , Atom oder Sublime .
  • Ein Terminal zum Ausführen von Shell-Befehlen mit installiertem NodeJS v9.
  • Ein Browser wie Chrome.
  • Der Beispielcode. Siehe dazu den nächsten Schritt.

2. Holen Sie sich den Beispielcode

Klonen Sie das GitHub-Repository über die Befehlszeile:

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

Importieren Sie die Starter-App

Öffnen oder importieren Sie mit Ihrer IDE die android_studio_folder.png cloud-functions-start Verzeichnis aus dem Beispielcodeverzeichnis. Dieses Verzeichnis enthält den Startcode für das Codelab, das aus einer voll funktionsfähigen Chat-Web-App besteht.

3. Erstellen Sie ein Firebase-Projekt und richten Sie Ihre App ein

Projekt erstellen

Klicken Sie in der Firebase Console auf Projekt hinzufügen und nennen Sie es FriendlyChat .

Klicken Sie auf Projekt erstellen .

Upgrade auf den Blaze-Plan

Um Cloud Functions for Firebase verwenden zu können, müssen Sie Ihr Firebase-Projekt auf den Blaze-Abrechnungsplan aktualisieren . Dazu müssen Sie Ihrem Google Cloud-Konto eine Kreditkarte oder ein anderes Abrechnungsinstrument hinzufügen.

Alle Firebase-Projekte, einschließlich derjenigen im Blaze-Plan, haben weiterhin Zugriff auf die kostenlosen Nutzungskontingente für Cloud Functions. Die in diesem Codelab beschriebenen Schritte fallen unter die Nutzungsbeschränkungen des kostenlosen Kontingents. Es fallen jedoch geringe Gebühren ( ca. 0,03 $ ) von Cloud Storage an, das zum Hosten Ihrer Cloud Functions-Build-Images verwendet wird.

Wenn Sie keinen Zugriff auf eine Kreditkarte haben oder den Blaze-Plan nicht fortsetzen möchten, sollten Sie die Firebase Emulator Suite verwenden, mit der Sie Cloud-Funktionen kostenlos auf Ihrem lokalen Computer emulieren können.

Aktivieren Sie Google Auth

Damit sich Benutzer in der App anmelden können, verwenden wir die Google-Authentifizierung, die aktiviert sein muss.

Öffnen Sie in der Firebase-Konsole den Abschnitt Erstellen > Authentifizierung > Registerkarte Anmeldemethode (oder klicken Sie hier, um dorthin zu gelangen). Aktivieren Sie dann den Google -Anmeldeanbieter und klicken Sie auf Speichern . Dadurch können sich Benutzer mit ihren Google-Konten in der Web-App anmelden.

Sie können auch den öffentlich zugänglichen Namen Ihrer App auf Friendly Chat festlegen:

8290061806aacb46.png

Cloud-Speicher aktivieren

Die App verwendet Cloud Storage, um Bilder hochzuladen. Um Cloud Storage für Ihr Firebase-Projekt zu aktivieren, besuchen Sie den Abschnitt „Storage “ und klicken Sie auf die Schaltfläche „Erste Schritte“ . Gehen Sie dort die Schritte durch, und für den Cloud-Speicherort gibt es einen zu verwendenden Standardwert. Klicken Sie anschließend auf Fertig .

Fügen Sie eine Web-App hinzu

Fügen Sie in der Firebase Console eine Web-App hinzu. Gehen Sie dazu zu den Projekteinstellungen und scrollen Sie nach unten zu App hinzufügen . Wählen Sie Web als Plattform und aktivieren Sie das Kontrollkästchen zum Einrichten von Firebase Hosting, registrieren Sie dann die App und klicken Sie für die restlichen Schritte auf Weiter , und klicken Sie zuletzt auf Weiter zur Konsole .

4. Installieren Sie die Firebase-Befehlszeilenschnittstelle

Mit der Firebase-Befehlszeilenschnittstelle (CLI) können Sie die Web-App lokal bereitstellen und Ihre Web-App und Cloud-Funktionen bereitstellen.

Um die CLI zu installieren oder zu aktualisieren, führen Sie den folgenden npm-Befehl aus:

npm -g install firebase-tools

Um zu überprüfen, ob die CLI korrekt installiert wurde, öffnen Sie eine Konsole und führen Sie Folgendes aus:

firebase --version

Stellen Sie sicher, dass die Version der Firebase CLI höher als 4.0.0 ist, damit sie über alle aktuellen Funktionen verfügt, die für Cloud Functions erforderlich sind. Wenn nicht, führen Sie npm install -g firebase-tools aus, um wie oben gezeigt zu aktualisieren.

Autorisieren Sie die Firebase CLI, indem Sie Folgendes ausführen:

firebase login

Stellen Sie sicher, dass Sie sich im Verzeichnis cloud-functions-start befinden, und richten Sie dann die Firebase-CLI für die Verwendung Ihres Firebase-Projekts ein:

firebase use --add

Wählen Sie als Nächstes Ihre Projekt-ID aus und folgen Sie den Anweisungen. Wenn Sie dazu aufgefordert werden, können Sie einen beliebigen Alias ​​auswählen, z. B. codelab .

5. Stellen Sie die Web-App bereit und führen Sie sie aus

Nachdem Sie Ihr Projekt importiert und konfiguriert haben, können Sie die Web-App zum ersten Mal ausführen! Öffnen Sie ein Terminalfenster, navigieren Sie zum Ordner cloud-functions-start und stellen Sie die Web-App für das Firebase-Hosting bereit:

firebase deploy --except functions

Dies ist die Konsolenausgabe, die Sie sehen sollten:

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

Öffnen Sie die Web-App

Die letzte Zeile sollte die Hosting-URL anzeigen. Die Web-App sollte jetzt von dieser URL bereitgestellt werden, die das Format https://<Projekt-ID>.firebaseapp.com haben sollte. Öffne es. Sie sollten die funktionierende Benutzeroberfläche einer Chat-App sehen.

Melden Sie sich über die Schaltfläche MIT GOOGLE ANMELDEN in der App an und fügen Sie gerne einige Nachrichten hinzu und posten Sie Bilder:

3b1284f5144b54f6.png

Wenn Sie sich zum ersten Mal in einem neuen Browser bei der App anmelden, vergewissern Sie sich, dass Sie Benachrichtigungen zulassen, wenn Sie dazu aufgefordert werden: 8b9d0c66dc36153d.png

Wir müssen Benachrichtigungen zu einem späteren Zeitpunkt aktivieren.

Wenn Sie versehentlich auf Blockieren geklickt haben, können Sie diese Einstellung ändern, indem Sie auf die Schaltfläche 🔒 Sicher links neben der URL in der Chrome Omnibar klicken und die Leiste neben Benachrichtigungen umschalten:

e926868b0546ed71.png

Jetzt fügen wir mithilfe des Firebase SDK for Cloud Functions einige Funktionen hinzu.

6. Das Funktionsverzeichnis

Mit Cloud Functions können Sie ganz einfach Code haben, der in der Cloud ausgeführt wird, ohne dass Sie einen Server einrichten müssen. Wir werden durchgehen, wie Funktionen erstellt werden, die auf Firebase Auth-, Cloud Storage- und Firebase Firestore-Datenbankereignisse reagieren. Beginnen wir mit Auth.

Wenn Sie das Firebase SDK für Cloud Functions verwenden, befindet sich Ihr Functions-Code (standardmäßig) im functions . Ihr Functions-Code ist auch eine Node.js- App und benötigt daher eine package.json , die einige Informationen über Ihre App enthält und Abhängigkeiten auflistet.

Um es Ihnen einfacher zu machen, haben wir bereits die Datei functions/index.js erstellt, in der Ihr Code abgelegt wird. Fühlen Sie sich frei, diese Datei zu überprüfen, bevor Sie fortfahren.

cd functions
ls

Wenn Sie mit Node.js nicht vertraut sind, wäre es hilfreich, mehr darüber zu erfahren, bevor Sie mit dem Codelab fortfahren.

Die Datei package.json listet bereits zwei erforderliche Abhängigkeiten auf: das Firebase SDK für Cloud Functions und das Firebase Admin SDK . Um sie lokal zu installieren, gehen Sie in den functions und führen Sie Folgendes aus:

npm install

Schauen wir uns nun die Datei index.js an:

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.

Wir importieren die erforderlichen Module und schreiben dann drei Funktionen anstelle der TODOs. Beginnen wir mit dem Importieren der erforderlichen Node-Module.

7. Importieren Sie die Module Cloud Functions und Firebase Admin

Während dieses Codelabs sind zwei Module erforderlich: firebase-functions ermöglicht das Schreiben von Cloud Functions-Triggern und -Protokollen, während firebase-admin die Verwendung der Firebase-Plattform auf einem Server mit Administratorzugriff ermöglicht, um Aktionen wie das Schreiben in Cloud Firestore oder das Senden von FCM-Benachrichtigungen auszuführen.

Ersetzen Sie in der Datei index.js das erste TODO durch Folgendes:

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.

Das Firebase Admin SDK kann automatisch konfiguriert werden, wenn es in einer Cloud Functions-Umgebung oder anderen Google Cloud Platform-Containern bereitgestellt wird, und dies geschieht, wenn wir admin.initializeApp() ohne Argumente aufrufen.

Lassen Sie uns nun eine Funktion hinzufügen, die ausgeführt wird, wenn sich ein Benutzer zum ersten Mal in der Chat-App anmeldet, und wir fügen eine Chatnachricht hinzu, um den Benutzer willkommen zu heißen.

8. Neue Benutzer willkommen heißen

Struktur von Chat-Nachrichten

Im FriendlyChat-Chat-Feed gepostete Nachrichten werden in Cloud Firestore gespeichert. Schauen wir uns die Datenstruktur an, die wir für eine Nachricht verwenden. Posten Sie dazu eine neue Nachricht im Chat mit der Aufschrift „Hello World“:

11f5a676fbb1a69a.png

Dies sollte folgendermaßen aussehen:

fe6d1c020d0744cf.png

Klicken Sie in der Firebase-Konsole im Abschnitt „Erstellen“ auf „Firestore-Datenbank“ . Sie sollten die Nachrichtensammlung und ein Dokument mit der von Ihnen geschriebenen Nachricht sehen:

442c9c10b5e2b245.png

Wie Sie sehen können, werden Chatnachrichten in Cloud Firestore als Dokument gespeichert, wobei die Attribute name , profilePicUrl , text und timestamp der messages hinzugefügt werden.

Begrüßungsnachrichten hinzufügen

Die erste Cloud-Funktion fügt eine Nachricht hinzu, die neue Benutzer im Chat willkommen heißt. Dazu können wir den Trigger functions.auth().onCreate verwenden, der die Funktion jedes Mal ausführt, wenn sich ein Benutzer zum ersten Mal in der Firebase-App anmeldet. Fügen Sie die addWelcomeMessages -Funktion in Ihre index.js Datei ein:

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.');
});

Das Hinzufügen dieser Funktion zum speziellen exports Objekt ist die Art und Weise, wie Node die Funktion außerhalb der aktuellen Datei zugänglich macht, und ist für Cloud-Funktionen erforderlich.

In der obigen Funktion fügen wir der Liste der Chatnachrichten eine neue Willkommensnachricht hinzu, die von „Firebase Bot“ gepostet wurde. Wir tun dies, indem wir die add Methode für die messages in Cloud Firestore verwenden, wo die Nachrichten des Chats gespeichert werden.

Da dies ein asynchroner Vorgang ist, müssen wir das Promise zurückgeben, das angibt, wann Cloud Firestore mit dem Schreiben fertig ist, damit die Cloud Functions nicht zu früh ausgeführt werden.

Cloud-Funktionen bereitstellen

Cloud Functions sind erst aktiv, nachdem Sie sie bereitgestellt haben. Führen Sie dazu dies in der Befehlszeile aus:

firebase deploy --only functions

Dies ist die Konsolenausgabe, die Sie sehen sollten:

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

Testen Sie die Funktion

Sobald die Funktion erfolgreich bereitgestellt wurde, benötigen Sie einen Benutzer, der sich zum ersten Mal anmeldet.

  1. Öffnen Sie Ihre App in Ihrem Browser mit der Hosting-URL (in Form von https://<project-id>.firebaseapp.com ).
  2. Als neuer Benutzer melden Sie sich zum ersten Mal in Ihrer App über die Schaltfläche Anmelden an.
  • Wenn Sie sich bereits bei der App angemeldet haben, können Sie die Firebase Console-Authentifizierung öffnen und Ihr Konto aus der Benutzerliste löschen. Melden Sie sich dann erneut an.

262535d1b1223c65.png

  1. After you sign in, a welcome message should be displayed automatically:

1c70e0d64b23525b.png

9. Images moderation

Users can upload all type of images in the chat, and it is always important to moderate offensive images, especially in public social platforms. In FriendlyChat, the images that are being published to the chat are stored into Google Cloud Storage .

With Cloud Functions, you can detect new image uploads using the functions.storage().onFinalize trigger. This will run every time a new file is uploaded or modified in Cloud Storage.

To moderate images, we'll go through the following process:

  1. Check if the image is flagged as Adult or Violent using the Cloud Vision API .
  2. If the image has been flagged, download it on the running Functions instance.
  3. Blur the image using ImageMagick .
  4. Upload the blurred image to Cloud Storage.

Enable the Cloud Vision API

Since we'll be using the Google Cloud Vision API in this function, you must enable the API on your firebase project. Follow this link , then select your Firebase project and enable the API:

5c77fee51ec5de49.png

Install dependencies

To moderate images, we'll use the Google Cloud Vision Client Library for Node.js, @google-cloud/vision , to run images through the Cloud Vision API to detect inappropriate images.

To install this package into your Cloud Functions app, run the following npm install --save command. Make sure that you do this from the functions directory.

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

This will install the package locally and add them as a declared dependency in your package.json file.

Import and configure dependencies

To import the dependencies that were installed and some Node.js core modules ( path , os and fs ) that we'll need in this section, add the following lines to the top of your index.js file:

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');

Since your function will run inside a Google Cloud environment, there is no need to configure the Cloud Storage and Cloud Vision libraries: they will be configured automatically to use your project.

Detecting inappropriate images

You'll be using the functions.storage.onChange Cloud Functions trigger, which runs your code as soon as a file or folder is created or modified in a Cloud Storage bucket. Add the blurOffensiveImages Function into your index.js file:

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.');
    });

Note that we added some configuration of the Cloud Functions instance that will run the function. With .runWith({memory: '2GB'}) , we're requesting that the instance gets 2GB of memory rather than the default, because this function is memory intensive.

When the function is triggered, the image is ran through the Cloud Vision API to detect if it is flagged as adult or violent. If the image is detected as inappropriate based on these criteria, we're blurring the image, which is done in the blurImage function as we'll see next.

Blurring the image

Add the following blurImage function in your index.js file:

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.');
}

In the above function, the image binary is downloaded from Cloud Storage. The image is then blurred using ImageMagick's convert tool, and the blurred version is re-uploaded on the Storage Bucket. Next, we delete the file on the Cloud Functions instance to free up some disk space, and we do this because the same Cloud Functions instance can get re-used and if files are not cleaned up, it could run out of disk space. Finally, we add a boolean to the chat message indicating the image was moderated, and this will trigger a refresh of the message on the client.

Deploy the Function

The Function will only be active after you've deployed it. On the command line, run firebase deploy --only functions :

firebase deploy --only functions

This is the console output you should see:

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

Test the function

Once the function has deployed successfully:

  1. Open your app in your browser using the hosting URL (in the form of https://<project-id>.firebaseapp.com ).
  2. Once signed into the app, upload an image: 4db9fdab56703e4a.png
  3. Choose your best offensive image to upload (or you can use this flesh eating Zombie !) and after a few moments, you should see your post refresh with a blurred version of the image: 83dd904fbaf97d2b.png

10. New Message Notifications

In this section, you will add a Cloud Function that sends notifications to participants of the chat when a new message is posted.

Using Firebase Cloud Messaging (FCM), you can reliably send notifications to users across platforms. To send a notification to a user, you need their FCM device token. The chat web app that we are using already collects device tokens from users when they open the app for the first time on a new browser or device. These tokens are stored in Cloud Firestore in the fcmTokens collection.

If you would like to learn how to get FCM device tokens on a web app, you can go through the Firebase Web Codelab .

Send notifications

To detect when new messages are posted, you'll be using the functions.firestore.document().onCreate Cloud Functions trigger, which runs your code when a new object is created at a given path of Cloud Firestore. Add the sendNotifications function into your index.js file:

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.');
    }
  });

In the Function above, we are gathering all users' device tokens from the Cloud Firestore database and sending a notification to each of these using the admin.messaging().sendToDevice function.

Cleanup the tokens

Lastly, we want to remove the tokens that are no longer valid. This happens when the token that we once got from the user is not being used by the browser or device anymore. For instance, this happens if the user has revoked the notification permission for the browser session. To do this, add the following cleanupTokens function in your index.js file:

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);
}

Deploy the Function

The function will only be active after you've deployed it, and to deploy it, run this in command line:

firebase deploy --only functions

This is the console output you should see:

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

Test the function

  1. Once the function has deployed successfully, open your app in your browser using the hosting URL (in the form of https://<project-id>.firebaseapp.com ).
  2. If you sign-in the app for the first time, make sure you allow notifications when prompted: 8b9d0c66dc36153d.png
  3. Close the chat app tab or display a different tab: Notifications appear only if the app is in the background. If you would like to learn how to receive messages while your app is in the foreground, have a look at our documentation .
  4. Using a different browser (or an Incognito window), sign into the app and post a message. You should see a notification displayed by the first browser: 45282ab12b28b926.png

11. Herzlichen Glückwunsch!

You have used the Firebase SDK for Cloud Functions and added server-side components to a chat app.

What we've covered

  • Authoring Cloud Functions using the Firebase SDK for Cloud Functions.
  • Trigger Cloud Functions based on Auth, Cloud Storage, and Cloud Firestore events.
  • Add Firebase Cloud Messaging support to your web app.
  • Deploy Cloud Functions using the Firebase CLI.

Next Steps

Learn More