ส่งการแจ้งเตือนสำหรับเว็บแอปโดยใช้ Cloud Messaging และ Cloud Functions

1. ภาพรวม

ในโค้ดแล็บนี้ คุณจะได้เรียนรู้วิธีใช้ Cloud Functions for Firebase เพื่อเพิ่มฟังก์ชันการทำงานให้กับเว็บแอปแชทโดยการส่งการแจ้งเตือนไปยังผู้ใช้แอปแชท

3b1284f5144b54f6.png

สิ่งที่คุณจะได้เรียนรู้

  • สร้างฟังก์ชันของ Google Cloud โดยใช้ Firebase SDK
  • ทริกเกอร์ Cloud Functions ตามเหตุการณ์ Auth, Cloud Storage และ Cloud Firestore
  • เพิ่มการรองรับ Firebase Cloud Messaging ลงในเว็บแอป

สิ่งที่ต้องมี

  • บัตรเครดิต Cloud Functions for Firebase ต้องใช้แพ็กเกจ Firebase Blaze ซึ่งหมายความว่าคุณจะต้องเปิดใช้การเรียกเก็บเงินในโปรเจ็กต์ Firebase โดยใช้บัตรเครดิต
  • IDE/โปรแกรมแก้ไขข้อความที่คุณเลือก เช่น WebStorm, Atom หรือ Sublime
  • เทอร์มินัลเพื่อเรียกใช้คำสั่งเชลล์โดยติดตั้ง NodeJS v9
  • เบราว์เซอร์ เช่น Chrome
  • โค้ดตัวอย่าง ดูขั้นตอนถัดไปสำหรับเรื่องนี้

2. รับโค้ดตัวอย่าง

โคลนที่เก็บ GitHub จากบรรทัดคำสั่งโดยใช้คำสั่งต่อไปนี้

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

นำเข้าแอปเริ่มต้น

ใช้ IDE เปิดหรือนำเข้าไดเรกทอรี android_studio_folder.pngcloud-functions-start จากไดเรกทอรีโค้ดตัวอย่าง ไดเรกทอรีนี้มีโค้ดเริ่มต้นสำหรับโค้ดแล็บ ซึ่งประกอบด้วยเว็บแอป Chat ที่ใช้งานได้อย่างเต็มรูปแบบ

3. สร้างโปรเจ็กต์ Firebase และตั้งค่าแอป

สร้างโปรเจ็กต์

  1. ลงชื่อเข้าใช้คอนโซล Firebase โดยใช้บัญชี Google
  2. คลิกปุ่มเพื่อสร้างโปรเจ็กต์ใหม่ แล้วป้อนชื่อโปรเจ็กต์ (เช่น FriendlyChat)
  3. คลิกต่อไป
  4. หากได้รับแจ้ง ให้อ่านและยอมรับข้อกำหนดของ Firebase แล้วคลิกต่อไป
  5. (ไม่บังคับ) เปิดใช้ความช่วยเหลือจาก AI ในคอนโซล Firebase (เรียกว่า "Gemini ใน Firebase")
  6. สำหรับ Codelab นี้ คุณไม่จำเป็นต้องใช้ Google Analytics ดังนั้นให้ปิดตัวเลือก Google Analytics
  7. คลิกสร้างโปรเจ็กต์ รอให้ระบบจัดสรรโปรเจ็กต์ แล้วคลิกดำเนินการต่อ

อัปเกรดเป็นแพ็กเกจ Blaze

หากต้องการใช้ Cloud Functions for Firebase และ Cloud Storage for Firebase โปรเจ็กต์ Firebase ของคุณต้องอยู่ในแพ็กเกจราคาแบบจ่ายเมื่อใช้ (Blaze) ซึ่งหมายความว่าโปรเจ็กต์ต้องลิงก์กับบัญชีการเรียกเก็บเงินในระบบคลาวด์

หากคุณไม่มีสิทธิ์เข้าถึงบัตรเครดิตหรือไม่สะดวกที่จะใช้แพ็กเกจราคา Blaze ต่อไป ให้ลองใช้ Firebase Emulator Suite ซึ่งจะช่วยให้คุณจำลอง Cloud Functions ได้ฟรีในเครื่องของคุณ

โปรเจ็กต์ Firebase ทั้งหมด รวมถึงโปรเจ็กต์ที่ใช้แพ็กเกจราคา Blaze จะยังคงมีสิทธิ์เข้าถึงโควต้าการใช้งาน Cloud Functions แบบไม่มีค่าใช้จ่าย ขั้นตอนที่ระบุไว้ในโค้ดแล็บนี้จะอยู่ภายในขีดจำกัดการใช้งานของรุ่นฟรี อย่างไรก็ตาม คุณจะเห็นค่าใช้จ่ายเล็กน้อย (ประมาณ $0.03) จาก Cloud Storage ซึ่งใช้เพื่อโฮสต์อิมเมจบิลด์ของ Cloud Functions

หากต้องการอัปเกรดโปรเจ็กต์เป็นแพ็กเกจ Blaze ให้ทำตามขั้นตอนต่อไปนี้

  1. ในคอนโซล Firebase ให้เลือกอัปเกรดแพ็กเกจ
  2. เลือกแพ็กเกจ Blaze ทำตามวิธีการบนหน้าจอเพื่อลิงก์บัญชีสำหรับการเรียกเก็บเงินใน Cloud กับโปรเจ็กต์
    หากคุณต้องสร้างบัญชีสำหรับการเรียกเก็บเงินใน Cloud เป็นส่วนหนึ่งของการอัปเกรดนี้ คุณอาจต้องกลับไปที่ขั้นตอนการอัปเกรดใน Firebase Console เพื่อทำการอัปเกรดให้เสร็จสมบูรณ์

เปิดใช้ Google Auth

หากต้องการให้ผู้ใช้ลงชื่อเข้าใช้แอป เราจะใช้การตรวจสอบสิทธิ์ของ Google ซึ่งต้องเปิดใช้

ในคอนโซล Firebase ให้เปิดส่วนสร้าง > การตรวจสอบสิทธิ์ > แท็บวิธีการลงชื่อเข้าใช้ (หรือคลิกที่นี่เพื่อไปที่แท็บดังกล่าว) จากนั้นเปิดใช้ผู้ให้บริการลงชื่อเข้าใช้ Google แล้วคลิกบันทึก ซึ่งจะช่วยให้ผู้ใช้ลงชื่อเข้าใช้เว็บแอปด้วยบัญชี Google ได้

นอกจากนี้ คุณยังตั้งชื่อที่แสดงต่อสาธารณะของแอปเป็น Friendly Chat ได้ด้วย

8290061806aacb46.png

ตั้งค่า Cloud Storage for Firebase

แอปใช้ Cloud Storage เพื่ออัปโหลดรูปภาพ

วิธีตั้งค่า Cloud Storage for Firebase ในโปรเจ็กต์ Firebase มีดังนี้

  1. ในแผงด้านซ้ายของคอนโซล Firebase ให้ขยายสร้าง แล้วเลือก Storage
  2. คลิกเริ่มต้นใช้งาน
  3. เลือกตำแหน่งสำหรับที่เก็บข้อมูลเริ่มต้น
    ที่เก็บข้อมูลใน US-WEST1, US-CENTRAL1 และ US-EAST1 จะใช้ประโยชน์จากระดับ"ใช้งานฟรีเสมอ" สำหรับ Google Cloud Storage ได้ ที่เก็บข้อมูลในตำแหน่งอื่นๆ ทั้งหมดจะเป็นไปตามราคาและการใช้งาน Google Cloud Storage
  4. คลิกเริ่มในโหมดทดสอบ อ่านข้อจำกัดความรับผิดเกี่ยวกับกฎความปลอดภัย
    อย่าเผยแพร่หรือแสดงแอปต่อสาธารณะโดยไม่ได้เพิ่มกฎความปลอดภัยสำหรับที่เก็บข้อมูลของคุณ
  5. คลิกสร้าง

เพิ่มเว็บแอป

ในคอนโซล Firebase ให้เพิ่มเว็บแอป โดยไปที่การตั้งค่าโปรเจ็กต์ แล้วเลื่อนลงไปที่เพิ่มแอป เลือกเว็บเป็นแพลตฟอร์ม แล้วเลือกช่องเพื่อตั้งค่า Firebase Hosting จากนั้นลงทะเบียนแอป แล้วคลิกถัดไปสำหรับขั้นตอนที่เหลือ สุดท้ายให้คลิกไปที่คอนโซล

4. ติดตั้งอินเทอร์เฟซบรรทัดคำสั่งของ Firebase

อินเทอร์เฟซบรรทัดคำสั่ง (CLI) ของ Firebase จะช่วยให้คุณแสดงเว็บแอปในเครื่อง รวมถึงทำให้ใช้งานเว็บแอปและ Cloud Functions ได้

หากต้องการติดตั้งหรืออัปเกรด CLI ให้เรียกใช้คำสั่ง npm ต่อไปนี้

npm -g install firebase-tools

หากต้องการยืนยันว่าได้ติดตั้ง CLI อย่างถูกต้องแล้ว ให้เปิดคอนโซลแล้วเรียกใช้คำสั่งต่อไปนี้

firebase --version

ตรวจสอบว่า Firebase CLI เป็นเวอร์ชันที่สูงกว่า 4.0.0 เพื่อให้มีฟีเจอร์ล่าสุดทั้งหมดที่จำเป็นสำหรับ Cloud Functions หากไม่ได้อัปเกรด ให้เรียกใช้ npm install -g firebase-tools เพื่ออัปเกรดตามที่แสดงด้านบน

ให้สิทธิ์ Firebase CLI โดยเรียกใช้คำสั่งต่อไปนี้

firebase login

ตรวจสอบว่าคุณอยู่ในไดเรกทอรี cloud-functions-start จากนั้นตั้งค่า Firebase CLI เพื่อใช้โปรเจ็กต์ Firebase โดยทำดังนี้

firebase use --add

จากนั้นเลือกรหัสโปรเจ็กต์และทำตามวิธีการ เมื่อได้รับแจ้ง คุณสามารถเลือกนามแฝงใดก็ได้ เช่น codelab

5. ทำให้เว็บแอปใช้งานได้และเรียกใช้

เมื่อนำเข้าและกำหนดค่าโปรเจ็กต์แล้ว คุณก็พร้อมที่จะเรียกใช้เว็บแอปเป็นครั้งแรก เปิดหน้าต่างเทอร์มินัล ไปที่โฟลเดอร์ cloud-functions-start แล้วทำให้เว็บแอปใช้งานได้ในโฮสติ้งของ Firebase โดยใช้คำสั่งต่อไปนี้

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 นี้ ซึ่งควรมีรูปแบบเป็น https://<project-id>.firebaseapp.com เปิด URL นี้ คุณควรเห็น UI การทำงานของแอปแชท

ลงชื่อเข้าใช้แอปโดยใช้ปุ่มลงชื่อเข้าใช้ด้วย Google และเพิ่มข้อความและโพสต์รูปภาพได้เลย

3b1284f5144b54f6.png

หากลงชื่อเข้าใช้แอปในเบราว์เซอร์ใหม่เป็นครั้งแรก โปรดตรวจสอบว่าคุณอนุญาตการแจ้งเตือนเมื่อได้รับข้อความแจ้ง 8b9d0c66dc36153d.png

เราจะต้องเปิดใช้การแจ้งเตือนในภายหลัง

หากคุณคลิกบล็อกโดยไม่ตั้งใจ คุณสามารถเปลี่ยนการตั้งค่านี้ได้โดยคลิกปุ่ม 🔒 ปลอดภัยทางด้านซ้ายของ URL ในแถบออมนิบาร์ของ Chrome แล้วสลับแถบข้างการแจ้งเตือน

e926868b0546ed71.png

ตอนนี้เราจะเพิ่มฟังก์ชันการทำงานบางอย่างโดยใช้ Firebase SDK สำหรับ Cloud Functions

6. ไดเรกทอรีฟังก์ชัน

Cloud Functions ช่วยให้คุณมีโค้ดที่ทำงานในระบบคลาวด์ได้อย่างง่ายดายโดยไม่ต้องตั้งค่าเซิร์ฟเวอร์ เราจะอธิบายวิธีสร้างฟังก์ชันที่ตอบสนองต่อเหตุการณ์ในฐานข้อมูล Firebase Auth, Cloud Storage และ Firebase Firestore มาเริ่มกันที่ Auth

เมื่อใช้ Firebase SDK สำหรับ Cloud Functions โค้ดฟังก์ชันจะอยู่ในไดเรกทอรี functions (โดยค่าเริ่มต้น) โค้ดฟังก์ชันยังเป็นแอป Node.js ด้วย จึงต้องมี package.json ที่ให้ข้อมูลบางอย่างเกี่ยวกับแอปและแสดงรายการการอ้างอิง

เราได้สร้างไฟล์ functions/index.js ไว้แล้วเพื่อให้คุณใช้งานได้ง่ายขึ้น ซึ่งเป็นที่ที่คุณจะวางโค้ดของคุณ โปรดตรวจสอบไฟล์นี้ก่อนดำเนินการต่อ

cd functions
ls

หากคุณไม่คุ้นเคยกับ Node.js การศึกษาข้อมูลเพิ่มเติมเกี่ยวกับ Node.js ก่อนที่จะทำ Codelab ต่อไปจะเป็นประโยชน์

ไฟล์ package.json แสดงการอ้างอิงที่จำเป็น 2 รายการอยู่แล้ว ได้แก่ Firebase SDK สำหรับ Cloud Functions และ Firebase Admin SDK หากต้องการติดตั้งในเครื่อง ให้ไปที่โฟลเดอร์ functions แล้วเรียกใช้คำสั่งต่อไปนี้

npm install

ตอนนี้มาดูไฟล์ 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.

เราจะนำเข้าโมดูลที่จำเป็น แล้วเขียนฟังก์ชัน 3 รายการแทนที่ TODO มาเริ่มด้วยการนำเข้าโมดูล Node ที่จำเป็นกัน

7. นำเข้าโมดูล Cloud Functions และ Firebase Admin

โมดูล 2 โมดูลจะต้องใช้ในระหว่าง Codelab นี้ โดย firebase-functions ช่วยให้เขียนทริกเกอร์และบันทึกของ Cloud Functions ได้ ส่วน firebase-admin ช่วยให้ใช้แพลตฟอร์ม Firebase ในเซิร์ฟเวอร์ที่มีสิทธิ์เข้าถึงระดับผู้ดูแลระบบเพื่อดำเนินการต่างๆ เช่น เขียนไปยัง Cloud Firestore หรือส่งการแจ้งเตือน FCM ได้

ในไฟล์ index.js ให้แทนที่ TODO แรกด้วยข้อความต่อไปนี้

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.

คุณกำหนดค่า Firebase Admin SDK ได้โดยอัตโนมัติเมื่อติดตั้งใช้งานในสภาพแวดล้อม Cloud Functions หรือคอนเทนเนอร์ Google Cloud Platform อื่นๆ และจะเกิดขึ้นเมื่อเราเรียกใช้ admin.initializeApp() โดยไม่มีอาร์กิวเมนต์

ตอนนี้มาเพิ่มฟังก์ชันที่จะทำงานเมื่อผู้ใช้ลงชื่อเข้าใช้แอปแชทเป็นครั้งแรกกัน และเราจะเพิ่มข้อความแชทเพื่อต้อนรับผู้ใช้

8. ต้อนรับผู้ใช้ใหม่

โครงสร้างข้อความใน Chat

ระบบจะจัดเก็บข้อความที่โพสต์ในฟีดแชทของ FriendlyChat ไว้ใน Cloud Firestore มาดูโครงสร้างข้อมูลที่เราใช้สำหรับข้อความกัน โดยให้โพสต์ข้อความใหม่ในแชทว่า "Hello World" ดังนี้

11f5a676fbb1a69a.png

ซึ่งควรปรากฏเป็น

fe6d1c020d0744cf.png

ในคอนโซล Firebase ให้คลิกฐานข้อมูล Firestore ในส่วนสร้าง คุณควรเห็นคอลเล็กชันข้อความและเอกสาร 1 รายการที่มีข้อความที่คุณเขียน

442c9c10b5e2b245.png

ดังที่เห็น ข้อความแชทจะจัดเก็บไว้ใน Cloud Firestore เป็นเอกสารที่มีการเพิ่มแอตทริบิวต์ name, profilePicUrl, text และ timestamp ลงในคอลเล็กชัน messages

การเพิ่มข้อความต้อนรับ

Cloud Function แรกจะเพิ่มข้อความต้อนรับผู้ใช้ใหม่เข้าสู่แชท เราใช้ทริกเกอร์ functions.auth().onCreate สำหรับกรณีนี้ได้ ซึ่งจะเรียกใช้ฟังก์ชันทุกครั้งที่ผู้ใช้ลงชื่อเข้าใช้แอป Firebase เป็นครั้งแรก เพิ่มฟังก์ชัน addWelcomeMessages ลงในไฟล์ 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.');
});

การเพิ่มฟังก์ชันนี้ลงในออบเจ็กต์ exports พิเศษเป็นวิธีของ Node ในการทำให้ฟังก์ชันเข้าถึงได้นอกไฟล์ปัจจุบัน และจำเป็นสำหรับ Cloud Functions

ในฟังก์ชันด้านบน เราจะเพิ่มข้อความต้อนรับใหม่ที่โพสต์โดย "Firebase Bot" ลงในรายการข้อความแชท เราทำเช่นนี้โดยใช้วิธี add ในคอลเล็กชัน messages ใน Cloud Firestore ซึ่งเป็นที่จัดเก็บข้อความของแชท

เนื่องจากการดำเนินการนี้เป็นการดำเนินการแบบไม่พร้อมกัน เราจึงต้องส่งคืน Promise ที่ระบุเวลาที่ Cloud Firestore เขียนเสร็จ เพื่อไม่ให้ Cloud Functions ทำงานเร็วเกินไป

ทำให้ Cloud Functions ใช้งานได้

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 ระบบจะจัดเก็บรูปภาพที่เผยแพร่ในแชทไว้ในที่เก็บข้อมูล Cloud Storage

Cloud Functions ช่วยให้คุณตรวจหาการอัปโหลดรูปภาพใหม่ได้โดยใช้ทริกเกอร์ functions.storage().onFinalize โดยจะทำงานทุกครั้งที่มีการอัปโหลดหรือแก้ไขไฟล์ใหม่ใน Cloud Storage

หากต้องการดูแลจัดการรูปภาพ เราจะดำเนินการตามกระบวนการต่อไปนี้

  1. ตรวจสอบว่ามีการแจ้งว่ารูปภาพเป็นเนื้อหาสำหรับผู้ใหญ่หรือมีความรุนแรงหรือไม่โดยใช้ Cloud Vision API
  2. หากมีการแจ้งว่ารูปภาพไม่เหมาะสม ให้ดาวน์โหลดรูปภาพในอินสแตนซ์ของฟังก์ชันที่กำลังทำงาน
  3. เบลอรูปภาพโดยใช้ ImageMagick
  4. อัปโหลดรูปภาพที่เบลอไปยัง Cloud Storage

เปิดใช้ Cloud Vision API

เนื่องจากเราจะใช้ Google Cloud Vision API ในฟังก์ชันนี้ คุณจึงต้องเปิดใช้ API ในโปรเจ็กต์ Firebase ทำตามลิงก์นี้ จากนั้นเลือกโปรเจ็กต์ Firebase แล้วเปิดใช้ API

5c77fee51ec5de49.png

ติดตั้งการอ้างอิง

หากต้องการกลั่นกรองรูปภาพ เราจะใช้ไลบรารีของไคลเอ็นต์ Google Cloud Vision สำหรับ Node.js, @google-cloud/vision เพื่อเรียกใช้รูปภาพผ่าน Cloud Vision API เพื่อตรวจหารูปภาพที่ไม่เหมาะสม

หากต้องการติดตั้งแพ็กเกจนี้ลงในแอป Cloud Functions ให้เรียกใช้คำสั่ง npm install --save ต่อไปนี้ ตรวจสอบว่าคุณดำเนินการนี้จากไดเรกทอรี functions

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

ซึ่งจะเป็นการติดตั้งแพ็กเกจในเครื่องและเพิ่มแพ็กเกจเป็นทรัพยากร Dependency ที่ประกาศไว้ในไฟล์ package.json

นำเข้าและกำหนดค่าทรัพยากร Dependency

หากต้องการนำเข้าทรัพยากร Dependency ที่ติดตั้งไว้และโมดูลหลักบางส่วนของ Node.js (path, os และ fs) ที่เราจะต้องใช้ในส่วนนี้ ให้เพิ่มบรรทัดต่อไปนี้ที่ด้านบนของไฟล์ 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');

เนื่องจากฟังก์ชันจะทำงานภายในสภาพแวดล้อม Google Cloud คุณจึงไม่จำเป็นต้องกำหนดค่าไลบรารี Cloud Storage และ Cloud Vision โดยระบบจะกำหนดค่าให้โดยอัตโนมัติเพื่อใช้โปรเจ็กต์ของคุณ

การตรวจหารูปภาพที่ไม่เหมาะสม

คุณจะใช้functions.storage.onChangeทริกเกอร์ Cloud Functions ซึ่งจะเรียกใช้โค้ดทันทีที่มีการสร้างหรือแก้ไขไฟล์หรือโฟลเดอร์ในที่เก็บข้อมูล Cloud Storage เพิ่มฟังก์ชัน blurOffensiveImages ลงในไฟล์ 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.');
    });

โปรดทราบว่าเราได้เพิ่มการกำหนดค่าอินสแตนซ์ Cloud Functions บางอย่างที่จะเรียกใช้ฟังก์ชัน ด้วย .runWith({memory: '2GB'}) เราขอให้อินสแตนซ์มีหน่วยความจำ 2 GB แทนค่าเริ่มต้น เนื่องจากฟังก์ชันนี้ใช้หน่วยความจำมาก

เมื่อฟังก์ชันทริกเกอร์ ระบบจะเรียกใช้รูปภาพผ่าน Cloud Vision API เพื่อตรวจหาว่ามีการแจ้งว่ารูปภาพเป็นภาพเปลือยหรือมีความรุนแรงหรือไม่ หากระบบตรวจพบว่ารูปภาพไม่เหมาะสมตามเกณฑ์เหล่านี้ เราจะเบลอรูปภาพ ซึ่งดำเนินการในblurImageฟังก์ชันตามที่เราจะเห็นต่อไป

การเบลอรูปภาพ

เพิ่มฟังก์ชัน blurImage ต่อไปนี้ในไฟล์ 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.');
}

ในฟังก์ชันข้างต้น ระบบจะดาวน์โหลดไบนารีของรูปภาพจาก Cloud Storage จากนั้นระบบจะเบลอรูปภาพโดยใช้เครื่องมือ convert ของ ImageMagick และอัปโหลดเวอร์ชันที่เบลออีกครั้งใน Storage Bucket จากนั้นเราจะลบไฟล์ในอินสแตนซ์ 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. การแจ้งเตือนข้อความใหม่

ในส่วนนี้ คุณจะเพิ่ม Cloud Function ที่ส่งการแจ้งเตือนไปยังผู้เข้าร่วมแชทเมื่อมีการโพสต์ข้อความใหม่

การใช้ Firebase Cloud Messaging (FCM) ช่วยให้คุณส่งการแจ้งเตือนไปยังผู้ใช้ในแพลตฟอร์มต่างๆ ได้อย่างน่าเชื่อถือ หากต้องการส่งการแจ้งเตือนไปยังผู้ใช้ คุณต้องมีโทเค็นอุปกรณ์ FCM ของผู้ใช้ เว็บแอปแชทที่เราใช้อยู่จะรวบรวมโทเค็นอุปกรณ์จากผู้ใช้เมื่อเปิดแอปเป็นครั้งแรกในเบราว์เซอร์หรืออุปกรณ์ใหม่ ระบบจะจัดเก็บโทเค็นเหล่านี้ไว้ใน Cloud Firestore ในคอลเล็กชัน fcmTokens

หากต้องการดูวิธีรับโทเค็นอุปกรณ์ FCM ในเว็บแอป โปรดไปที่ Firebase Web Codelab

ส่งการแจ้งเตือน

หากต้องการตรวจหาเมื่อมีการโพสต์ข้อความใหม่ คุณจะต้องใช้functions.firestore.document().onCreateทริกเกอร์ Cloud Functions ซึ่งจะเรียกใช้โค้ดเมื่อมีการสร้างออบเจ็กต์ใหม่ในเส้นทางที่กำหนดของ Cloud Firestore เพิ่มฟังก์ชัน sendNotifications ลงในไฟล์ 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.');
    }
  });

ในฟังก์ชันด้านบน เราจะรวบรวมโทเค็นอุปกรณ์ของผู้ใช้ทั้งหมดจากฐานข้อมูล Cloud Firestore และส่งการแจ้งเตือนไปยังผู้ใช้แต่ละรายโดยใช้ฟังก์ชัน admin.messaging().sendToDevice

ล้างข้อมูลโทเค็น

สุดท้าย เราต้องการนำโทเค็นที่ใช้ไม่ได้อีกต่อไปออก ปัญหานี้เกิดขึ้นเมื่อเบราว์เซอร์หรืออุปกรณ์ไม่ได้ใช้โทเค็นที่เราเคยได้รับจากผู้ใช้อีกต่อไป เช่น กรณีที่ผู้ใช้เพิกถอนสิทธิ์การแจ้งเตือนสำหรับเซสชันเบราว์เซอร์ โดยให้เพิ่มฟังก์ชัน cleanupTokens ต่อไปนี้ในไฟล์ 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);
}

ทําให้ฟังก์ชันใช้งานได้

ฟังก์ชันนี้จะทำงานหลังจากที่คุณติดตั้งใช้งานแล้วเท่านั้น หากต้องการติดตั้งใช้งาน ให้เรียกใช้คำสั่งนี้ในบรรทัดคำสั่ง

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. เมื่อฟังก์ชันได้รับการติดตั้งใช้งานเรียบร้อยแล้ว ให้เปิดแอปในเบราว์เซอร์โดยใช้ URL การโฮสต์ (ในรูปแบบ https://<project-id>.firebaseapp.com)
  2. หากลงชื่อเข้าใช้แอปเป็นครั้งแรก โปรดอนุญาตการแจ้งเตือนเมื่อระบบขอ 8b9d0c66dc36153d.png
  3. ปิดแท็บแอปแชทหรือแสดงแท็บอื่น การแจ้งเตือนจะปรากฏขึ้นก็ต่อเมื่อแอปทำงานในเบื้องหลังเท่านั้น หากต้องการดูวิธีรับข้อความขณะที่แอปอยู่ในเบื้องหน้า โปรดดูเอกสารประกอบ
  4. ใช้เบราว์เซอร์อื่น (หรือหน้าต่างที่ไม่ระบุตัวตน) ลงชื่อเข้าใช้แอป แล้วโพสต์ข้อความ คุณควรเห็นการแจ้งเตือนที่แสดงโดยเบราว์เซอร์แรก 45282ab12b28b926.png

11. ยินดีด้วย

คุณใช้ Firebase SDK สำหรับ Cloud Functions และเพิ่มคอมโพเนนต์ฝั่งเซิร์ฟเวอร์ลงในแอปแชท

สิ่งที่เราได้พูดถึง

  • การเขียน Cloud Functions โดยใช้ Firebase SDK สำหรับ Cloud Functions
  • ทริกเกอร์ Cloud Functions ตามเหตุการณ์ Auth, Cloud Storage และ Cloud Firestore
  • เพิ่มการรองรับ Firebase Cloud Messaging ลงในเว็บแอป
  • ทำให้ Cloud Functions ใช้งานได้โดยใช้ Firebase CLI

ขั้นตอนถัดไป

ดูข้อมูลเพิ่มเติม