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

1. ภาพรวม

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

3b1284f5144b54f6.png

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

  • สร้าง Google Cloud Functions โดยใช้ 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 และตั้งค่าแอป

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

ในคอนโซล Firebase ให้คลิกเพิ่มโปรเจ็กต์ แล้วตั้งชื่อว่า FriendlyChat

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

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

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

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

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

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

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

เปิดใช้ Google Auth

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

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

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

8290061806aacb46.png

ตั้งค่า Cloud Storage for Firebase

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

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

  1. ในแผงด้านซ้ายของคอนโซล Firebase ให้ขยายบิลด์ แล้วเลือกพื้นที่เก็บข้อมูล
  2. คลิกเริ่มต้นใช้งาน
  3. เลือกตำแหน่งสำหรับที่เก็บข้อมูล Storage เริ่มต้น
    ที่เก็บข้อมูลใน 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 ในแถบ Omnibar ของ Chrome แล้วสลับแถบข้างการแจ้งเตือน

e926868b0546ed71.png

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

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

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

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

เราได้สร้างไฟล์ functions/index.js ไว้ให้แล้วสำหรับใส่โค้ดของคุณ คุณสามารถตรวจสอบไฟล์นี้ก่อนดำเนินการต่อได้

cd functions
ls

หากคุณไม่คุ้นเคยกับ Node.js คุณควรดูข้อมูลเพิ่มเติมเกี่ยวกับภาษานี้ก่อนทำโค้ดแล็บต่อ

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

262535d1b1223c65.png

  1. หลังจากลงชื่อเข้าใช้แล้ว ข้อความต้อนรับจะปรากฏขึ้นโดยอัตโนมัติ

1c70e0d64b23525b.png

9. การดูแลรูปภาพ

ผู้ใช้สามารถอัปโหลดรูปภาพทุกประเภทในแชท และการดูแลรูปภาพที่ไม่เหมาะสมเป็นสิ่งสําคัญเสมอ โดยเฉพาะอย่างยิ่งในแพลตฟอร์มโซเชียลแบบสาธารณะ ใน FriendlyChat รูปภาพที่เผยแพร่ในแชทจะจัดเก็บไว้ในที่เก็บข้อมูล Cloud Storage

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

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

  1. ตรวจสอบว่ารูปภาพถูกแจ้งว่าไม่เหมาะสมสําหรับผู้ใหญ่หรือมีความรุนแรงหรือไม่โดยใช้ Cloud Vision API
  2. หากมีการแจ้งว่ารูปภาพไม่เหมาะสม ให้ดาวน์โหลดรูปภาพในอินสแตนซ์ Functions ที่ทำงานอยู่
  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

ซึ่งจะติดตั้งแพ็กเกจในเครื่องและเพิ่มเป็นข้อกำหนดที่ประกาศไว้ในไฟล์ 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 และอัปโหลดเวอร์ชันเบลอลงในที่เก็บข้อมูลอีกครั้ง จากนั้นเราจะลบไฟล์ในอินสแตนซ์ 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. เลือกรูปภาพที่ไม่เหมาะสมที่สุดที่จะอัปโหลด (หรือจะใช้ซอมบี้กินเนื้อนี้ก็ได้) และหลังจากผ่านไป 2-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

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

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