Firebase 雲函數

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

3b1284f5144b54f6.png

你會學到什麼

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

你需要什麼

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

克隆GitHub的庫在命令行:

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

導入入門應用

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

創建項目

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

單擊創建項目

升級到 Blaze 計劃

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

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

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

啟用 Google 身份驗證

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

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

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

8290061806aacb46.png

啟用雲存儲

該應用程序使用雲存儲上傳圖片。要在火力地堡項目能夠訪問雲存儲的存儲部分,然後點擊開始使用按鈕。然後點擊了它,當你收到有關安全規則的免責聲明。

842ad84821323ef5.png

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的實例。

現在您已經導入並配置了您的項目,您已準備好首次運行 Web 應用程序。在打開控制台cloud-functions-start文件夾,運行firebase deploy --except functions這樣只會部署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 應用程序,該 URL 的格式應為 https://<project-id>.firebaseapp.com。打開它。您應該會看到聊天應用程序的運行 UI。

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

3b1284f5144b54f6.png

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

我們需要您稍後啟用通知。

如果您不小心點擊了,你可以在左邊在Chrome Omnibar的URL,並選擇通知🔒安全按鈕,點擊更改此設置>始終在本網站允許

e926868b0546ed71.png

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

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

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

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

cd functions
ls

如果你不熟悉的Node.js這將有助於更多地了解它繼續代碼實驗室之前。

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

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 模塊。

兩個模塊將本程式碼實驗室中是必需的,在firebase-functions模塊允許我們編寫雲功能觸發規則,而firebase-admin模塊允許我們使用火力地堡平台管理員權限的服務器上,例如寫入Cloud 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.

Firebase Admin SDK 在 Cloud Functions 環境或其他 Google Cloud Platform 容器上部署時可以自動配置。這是我們做的時候調用上面admin.initializeApp();

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

聊天消息結構

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

11f5a676fbb1a69a.png

這應該顯示為:

fe6d1c020d0744cf.png

在你的火力地堡的應用程序控制台單擊數據庫下的開發部分。您應該會看到消息集合和一個包含您所寫消息的文檔:

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) => {
  console.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(),
  });
  console.log('Welcome message written to database.');
});

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

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

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

部署函數

該功能僅在您部署後才處於活動狀態。在命令行中運行firebase deploy --only 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

用戶可以在聊天中上傳所有類型的圖片,並且緩和令人反感的圖片總是很重要的,尤其是在公共社交平台上。在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 包:

  • 谷歌的雲計算願景客戶端庫Node.js的: @谷歌雲/視覺運行通過雲願景API的圖像來檢測不良的圖像。
  • 使Node.js庫使我們能夠運行的進程:子進程,承諾自ImageMagick的命令行工具來運行ImageMagick的自帶的所有功能實例預裝。

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

npm install --save @google-cloud/vision@0.12.0 child-process-promise@2.2.1

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

導入和配置依賴

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

索引.js

const Vision = require('@google-cloud/vision');
const vision = new Vision();
const spawn = require('child-process-promise').spawn;

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 image = {
        source: {imageUri: `gs://${object.bucket}/${object.name}`},
      };

      // Check the image content using the Cloud Vision API.
      const batchAnnotateImagesResponse = await vision.safeSearchDetection(image);
      const safeSearchResult = batchAnnotateImagesResponse[0].safeSearchAnnotation;
      const Likelihood = Vision.types.Likelihood;
      if (Likelihood[safeSearchResult.adult] >= Likelihood.LIKELY ||
          Likelihood[safeSearchResult.violence] >= Likelihood.LIKELY) {
        console.log('The image', object.name, 'has been detected as inappropriate.');
        return blurImage(object.name);
      }
      console.log('The image', object.name, 'has been detected as OK.');
    });

請注意,我們添加了雲功能實例的一些配置將運行功能,具有.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});
  console.log('Image has been downloaded to', tempLocalFile);
  // Blur the image using ImageMagick.
  await spawn('convert', [tempLocalFile, '-channel', 'RGBA', '-blur', '0x24', tempLocalFile]);
  console.log('Image has been blurred');
  // Uploading the Blurred image back into the bucket.
  await bucket.upload(tempLocalFile, {destination: filePath});
  console.log('Blurred image has been uploaded to', filePath);
  // Deleting the local file to free up disk space.
  fs.unlinkSync(tempLocalFile);
  console.log('Deleted local file.');
  // Indicate that the message has been moderated.
  await admin.firestore().collection('messages').doc(messageId).update({moderated: true});
  console.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

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

使用火力地堡雲端通訊(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);
      console.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) {
     console.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

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

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

我們涵蓋的內容

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

下一步

了解更多