Firebase 雲函數

1. 概述

在此 Codelab 中,您將了解如何使用適用於 Google Cloud Functions 的 Firebase SDK 來改進聊天網絡應用,以及如何使用 Cloud Functions 向聊天應用的用戶發送通知。

3b1284f5144b54f6.png

你會學到什麼

  • 使用 Firebase SDK 創建 Google Cloud Functions。
  • 根據身份驗證、Cloud Storage 和 Cloud Firestore 事件觸發 Cloud Functions。
  • 將 Firebase 雲消息傳遞支持添加到您的 Web 應用程序。

你需要什麼

  • 一張信用卡。 Cloud Functions for Firebase 需要 Firebase Blaze 計劃,這意味著您必須使用信用卡對 Firebase 項目啟用計費。
  • 您所選擇的IDE /文本編輯器如WebStorm原子崇高
  • 在安裝了 NodeJS v9 的情況下運行 shell 命令的終端。
  • Chrome 等瀏覽器。
  • 示例代碼。請參閱下一步。

2.獲取示例代碼

克隆GitHub的庫在命令行:

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

導入入門應用

使用您的 IDE,打開或導入android_studio_folder.png cloud-functions-start從樣本代碼目錄的目錄。此目錄包含代碼實驗室的起始代碼,該代碼實驗室由功能齊全的聊天 Web 應用程序組成。

3. 創建 Firebase 項目並設置您的應用

創建項目

火力地堡控制台,單擊添加項目,並調用它FriendlyChat。

單擊創建項目

升級到 Blaze 計劃

為了使用雲功能進行火力地堡,你將不得不upgade你的火力地堡計劃的火焰計費計劃。這將要求您將信用卡或其他結算方式添加到您的 Google Cloud 帳戶。

所有 Firebase 項目,包括 Blaze 計劃中的項目,仍然可以訪問 Cloud Functions 的免費使用配額。此 Codelab 中概述的步驟將在免費層使用限制範圍內。但是,你會看到小的費用(約$ 0.03 ,從雲存儲),它是用來承載您的雲功能構建的圖像。

如果你沒有獲得一張信用卡或不舒服與火焰計劃繼續進行,考慮使用火力地堡模擬器套房,這將讓你模仿你的本地計算機上的免費雲功能。

啟用 Google 身份驗證

為了讓用戶登錄應用程序,我們將使用需要啟用的 Google 身份驗證。

在火力地堡控制台,打開Build部分>驗證>登錄方法選項卡(或點擊這裡去那裡)。然後,使谷歌登錄的提供者,然後單擊保存。這將允許用戶使用他們的 Google 帳戶登錄網絡應用程序。

此外,隨意設置你的應用程序,以友好的交談的面向公眾的名稱:

8290061806aacb46.png

啟用雲存儲

該應用程序使用雲存儲上傳圖片。要在火力地堡項目實現雲存儲,訪問存儲部分,然後點擊開始使用按鈕。執行那裡的步驟,對於 Cloud Storage 位置,將使用默認值。點擊之後完成

添加 Web 應用程序

在 Firebase 控制台上,添加一個網絡應用。要做到這一點,去項目設置和向下滾動添加應用程序。挑選網絡為平台,查看包裝盒上設置火力地堡主機,然後註冊應用程序,然後單擊下一步的步驟剩餘部分,最後點擊繼續安慰

4. 安裝 Firebase 命令行界面

Firebase 命令行界面 (CLI) 將允許您在本地為 Web 應用程序提供服務並部署您的 Web 應用程序和 Cloud Functions。

要安裝或升級 CLI,請運行以下 npm 命令:

npm -g install firebase-tools

要驗證 CLI 是否已正確安裝,請打開控制台並運行:

firebase --version

確保火力地堡CLI的版本是4.0.0以上,使其擁有所有必需的最新雲功能特徵。如果沒有,運行npm install -g firebase-tools如上圖所示升級。

通過運行以下命令授權 Firebase CLI:

firebase login

請確保你在cloud-functions-start目錄,然後設置火力地堡CLI使用您的火力地堡項目:

firebase use --add

接下來,選擇您的項目 ID 並按照說明進行操作。出現提示時,你可以選擇任何別名,如codelab

5. 部署並運行 Web 應用程序

現在您已經導入並配置了您的項目,您已準備好第一次運行 Web 應用程序!打開一個終端窗口,導航到cloud-functions-start的文件夾,並部署web應用程序使用託管火力地堡:

firebase deploy --except functions

這是您應該看到的控制台輸出:

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

打開網絡應用

最後一行應顯示主機URL。現在應從此 URL 提供 Web 應用程序,其格式應為 https://<project-id>.firebaseapp.com。打開它。您應該會看到聊天應用程序的運行 UI。

登錄到應用程序使用的登錄與Google按鈕,隨意添加一些消息和發表圖片:

3b1284f5144b54f6.png

如果您是第一次在新瀏覽器上登錄該應用程序,請確保在出現提示時允許通知: 8b9d0c66dc36153d.png

我們需要稍後啟用通知。

如果您不小心點擊了,您可以通過點擊🔒安全按鈕左側在Chrome Omnibar的URL和切換旁邊的欄通知更改此設置:

e926868b0546ed71.png

現在,我們將使用 Firebase SDK for Cloud Functions 添加一些功能。

6. 函數目錄

Cloud Functions 允許您輕鬆擁有在雲中運行的代碼,而無需設置服務器。我們將逐步介紹如何構建對 Firebase 身份驗證、雲存儲和 Firebase Firestore 數據庫事件做出反應的函數。讓我們從 Auth 開始。

當使用SDK火力地堡的雲功能,你的函數代碼將住在functions目錄(默認)。你的函數代碼也是一個Node.js的應用程序,因此需要package.json ,讓你的應用程序,並列出了相關的一些信息。

為了讓您更容易,我們已經創建了functions/index.js文件在您的代碼會。在繼續之前,請隨時檢查此文件。

cd functions
ls

如果你不熟悉Node.js的,以前更多地了解它繼續代碼實驗室將是有益的。

package.json文件已經列出了兩個需要的依賴:在火力地堡SDK雲功能火力地堡管理員SDK 。要在本地安裝它們,到functions夾,然後運行:

npm install

現在讓我們來看看index.js文件:

索引.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.

我們將導入所需的模塊,然後編寫三個函數來代替 TODO。讓我們從導入所需的 Node 模塊開始。

7. 導入 Cloud Functions 和 Firebase 管理模塊

兩個模塊將本程式碼實驗室中要求: firebase-functions允許寫雲功能觸發器和日誌,而firebase-admin能夠使用火力地堡平台與服務器上的管理員權限來做,比如寫入雲公司的FireStore或發送FCM通知的操作。

index.js文件,替換第一個TODO有以下情況:

索引.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.

在火力地堡管理員SDK可以在部署到雲環境的功能或其他谷歌雲平台集裝箱進行自動配置,而出現這種情況時,我們稱之為admin.initializeApp()不帶參數。

現在,讓我們添加一個在用戶第一次登錄聊天應用程序時運行的函數,我們將添加一條聊天消息來歡迎用戶。

8. 歡迎新用戶

聊天消息結構

發佈到 FriendlyChat 聊天源的消息存儲在 Cloud Firestore 中。讓我們看看我們用於消息的數據結構。為此,請在聊天中發布一條新消息,上面寫著“Hello World”:

11f5a676fbb1a69a.png

這應該顯示為:

fe6d1c020d0744cf.png

在火力地堡控制台,點擊公司的FireStore數據庫下的Build部分。您應該會看到消息集合和一個包含您所寫消息的文檔:

442c9c10b5e2b245.png

正如你所看到的,聊天消息存儲在雲計算公司的FireStore與文件nameprofilePicUrltexttimestamp添加到屬性messages收集。

添加歡迎信息

第一個雲功能補充說,歡迎新用戶的聊天消息。對於這一點,我們可以使用觸發器functions.auth().onCreate ,該用戶登錄,在在火力地堡應用程序在第一時間每次運行的功能。添加addWelcomeMessages功能到您的index.js文件:

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

添加此功能的特殊exports目標是使當前文件的功能來訪問外部節點的方式和所需的雲功能。

在上面的函數中,我們將“Firebase Bot”發布的新歡迎消息添加到聊天消息列表中。我們通過這樣add的方法, messages採集雲公司的FireStore,這是聊天的信息的存儲位置。

由於這是一個異步操作,我們需要返回的承諾表明,當雲計算公司的FireStore寫完所以雲功能不太早執行。

部署雲功能

Cloud Functions 只有在您部署它們後才會處於活動狀態。為此,請在命令行上運行:

firebase deploy --only functions

這是您應該看到的控制台輸出:

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

測試功能

成功部署函數後,您需要有一個首次登錄的用戶。

  1. 打開你的應用程序使用託管URL瀏覽器(以下形式https://<project-id>.firebaseapp.com )。
  2. 隨著新的用戶,請登錄使用登錄按鈕在你的應用程序中的第一次。

262535d1b1223c65.png

  1. 登錄後,應自動顯示歡迎消息:

1c70e0d64b23525b.png

9. 圖片審核

用戶可以在聊天中上傳所有類型的圖片,並且緩和令人反感的圖片總是很重要的,尤其是在公共社交平台上。在FriendlyChat,正在發布到聊天的圖像存儲到谷歌雲存儲

隨著雲計算的功能,可以檢測使用新的圖像上傳functions.storage().onFinalize觸發。每次在 Cloud Storage 中上傳或修改新文件時,這都會運行。

要審核圖像,我們將執行以下過程:

  1. 檢查圖像是使用標記為成人或暴力雲願景API
  2. 如果圖像已被標記,請將其下載到正在運行的 Functions 實例上。
  3. 利用模糊圖像ImageMagick的
  4. 將模糊的圖像上傳到 Cloud Storage。

啟用 Cloud Vision API

由於我們將在此函數中使用 Google Cloud Vision API,因此您必須在 Firebase 項目中啟用該 API。按照此鏈接,然後選擇您的火力地堡項目並啟用該API:

5c77fee51ec5de49.png

安裝依賴

要適度的圖像,我們將使用谷歌雲願景客戶端庫Node.js的, @谷歌雲/遠景,通過雲願景API運行圖像檢測不當圖片。

安裝這個軟件包到你的雲計算功能的應用程序,運行以下npm install --save命令。請確保您從做這個functions目錄。

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

這將在本地安裝包,並將其添加為您的一個聲明的依賴性package.json文件。

導入和配置依賴

要導入已安裝的依賴和Node.js的一些核心模塊( pathos以及fs ),我們就需要在本節中,添加以下行到頂部index.js文件:

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

由於您的函數將在 GCP 環境中運行,因此無需配置 Cloud Storage 和 Cloud Vision 庫:它們將自動配置為使用您的項目。

檢測不當圖像

您將使用functions.storage.onChange雲功能觸發,這只要一個文件或文件夾中創建或在雲端存儲修改運行代碼。添加blurOffensiveImages功能到您的index.js文件:

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

請注意,我們添加了一些將運行該函數的 Cloud Functions 實例的配置。隨著.runWith({memory: '2GB'})我們請求的情況下獲得的記憶,而不是默認的2GB,因為這個功能需要佔用大量內存。

當該功能被觸發時,圖像會通過 Cloud Vision API 運行以檢測它是否被標記為成人或暴力。如果圖像是基於這些標準檢測為不恰當的,我們的圖像模糊,這是在做blurImage功能,我們將看到這一點。

圖像模糊

添加以下blurImage功能在您的index.js文件:

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

在上述函數中,圖像二進製文件是從 Cloud Storage 下載的。該圖像,然後使用ImageMagick的模糊convert工具,而模糊的版本是重新上載於存儲桶。接下來,我們刪除 Cloud Functions 實例上的文件以釋放一些磁盤空間,我們這樣做是因為可以重複使用相同的 Cloud Functions 實例,如果不清理文件,它可能會耗盡磁盤空間。最後,我們向聊天消息添加一個布爾值,指示圖像已被審核,這將觸發客戶端上的消息刷新。

部署函數

該功能只有在您部署後才會處於活動狀態。在命令行中運行firebase deploy --only functions

firebase deploy --only functions

這是您應該看到的控制台輸出:

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

測試功能

成功部署函數後:

  1. 打開你的應用程序使用託管URL瀏覽器(以下形式https://<project-id>.firebaseapp.com )。
  2. 登錄應用程序後,上傳圖片: 4db9fdab56703e4a.png
  3. 選擇你最好的進攻要上傳的圖片(或者你可以使用這個食肉殭屍!),並在一段時間後,你應該看到您的帖子刷新與圖像的模糊版本: 83dd904fbaf97d2b.png

10. 新消息通知

在本節中,您將添加一個雲功能,該功能在發布新消息時向聊天參與者發送通知。

使用火力地堡雲端通訊(FCM),您可以可靠地向用戶發送通知跨平台。要向用戶發送通知,您需要他們的 FCM 設備令牌。當用戶在新瀏覽器或設備上第一次打開應用程序時,我們正在使用的聊天網絡應用程序已經從用戶那裡收集設備令牌。這些令牌被存儲在雲公司的FireStore在fcmTokens集合。

如果您想了解如何獲得一個Web應用程序FCM設備令牌,你可以通過火力地堡網頁程式碼實驗室

發送通知

為了檢測當有新的消息發布後,您可以使用functions.firestore.document().onCreate ,當在雲公司的FireStore給定的路徑創建一個新的對象上運行代碼的雲功能觸發。添加sendNotifications功能到您的index.js文件:

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

在上面的功能,我們正在收集從雲數據庫的FireStore所有用戶的裝置憑證和發送通知到每個這些使用admin.messaging().sendToDevice功能。

清理令牌

最後,我們要刪除不再有效的令牌。當瀏覽器或設備不再使用我們曾經從用戶那裡獲得的令牌時,就會發生這種情況。例如,如果用戶撤銷了瀏覽器會話的通知權限,就會發生這種情況。要做到這一點,添加以下cleanupTokens在你的函數index.js文件:

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

部署函數

該功能僅在您部署後才處於活動狀態,要部署它,請在命令行中運行:

firebase deploy --only functions

這是您應該看到的控制台輸出:

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

測試功能

  1. 一旦功能已成功部署,使用託管的網址在瀏覽器中打開應用(在形式https://<project-id>.firebaseapp.com )。
  2. 如果您是第一次登錄該應用程序,請確保在出現提示時允許通知: 8b9d0c66dc36153d.png
  3. 關閉聊天應用程序選項卡或顯示不同的選項卡:僅當應用程序在後台時才會顯示通知。如果你想學習如何當你的應用程序是在前台接收郵件,看看我們的文檔
  4. 使用不同的瀏覽器(或隱身窗口),登錄應用程序並發布消息。您應該會看到第一個瀏覽器顯示的通知: 45282ab12b28b926.png

11. 恭喜!

您已使用 Firebase SDK for Cloud Functions 並將服務器端組件添加到聊天應用程序。

我們涵蓋的內容

  • 使用 Firebase SDK for Cloud Functions 創作 Cloud Functions。
  • 根據身份驗證、Cloud Storage 和 Cloud Firestore 事件觸發 Cloud Functions。
  • 將 Firebase 雲消息傳遞支持添加到您的 Web 應用程序。
  • 使用 Firebase CLI 部署 Cloud Functions。

下一步

了解更多