إرسال الإشعارات من أحد تطبيقات الويب باستخدام "المراسلة عبر السحابة الإلكترونية" و"وظائف السحابة الإلكترونية"

1- نظرة عامة

في هذا الدليل التعليمي حول الرموز البرمجية، ستتعرّف على كيفية استخدام وظائف السحابة الإلكترونية لبرنامج Firebase لإضافة وظيفة إلى تطبيق ويب للمحادثات من خلال إرسال إشعارات إلى مستخدمي تطبيق المحادثات.

3b1284f5144b54f6.png

ما ستتعرّف عليه

  • أنشئ وظائف Google Cloud باستخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase.
  • يمكنك بدء وظائف السحابة الإلكترونية استنادًا إلى أحداث Auth وCloud Storage وCloud Firestore.
  • أضِف ميزة "المراسلة عبر السحابة الإلكترونية من Firebase" إلى تطبيق الويب.

المتطلبات

  • بطاقة ائتمان تتطلّب ميزة "وظائف السحابة الإلكترونية لبرنامج Firebase" خطة Firebase Blaze، ما يعني أنّه عليك تفعيل الفوترة في مشروعك على Firebase باستخدام بطاقة ائتمان.
  • بيئة تطوير البرامج/محرر النصوص الذي تختاره، مثل WebStorm أو Atom أو Sublime
  • وحدة طرفية لتشغيل أوامر shell مع تثبيت الإصدار 9 من NodeJS
  • متصفح، مثل Chrome
  • نموذج التعليمات البرمجية يُرجى الاطّلاع على الخطوة التالية لمعرفة كيفية إجراء ذلك.

2- الحصول على نموذج الرمز

استنسِخ مستودع GitHub من سطر الأوامر:

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

استيراد التطبيق النموذجي

باستخدام بيئة تطوير البرامج المتكاملة (IDE)، افتح أو استورِد دليل android_studio_folder.pngcloud-functions-start من دليل نماذج الرموز البرمجية. يحتوي هذا الدليل على الرمز البرمجي الأوّلي لمشروع Codelab الذي يتألف من تطبيق ويب Chat يعمل بكامل طاقته.

3- إنشاء مشروع على Firebase وإعداد تطبيقك

إنشاء مشروع

في وحدة تحكُّم Firebase، انقر على إضافة مشروع واسمه FriendlyChat.

انقر على إنشاء مشروع.

الترقية إلى خطة Blaze

لاستخدام "وظائف السحابة الإلكترونية لبرنامج Firebase" و"مساحة تخزين السحابة الإلكترونية لبرنامج 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"، افتح قسم الإصدار > علامة التبويب المصادقة > طريقة تسجيل الدخول (أو انقر على هذا الرابط للانتقال إلى هناك). بعد ذلك، فعِّل مقدّم خدمة تسجيل الدخول في Google وانقر على حفظ. سيتيح ذلك للمستخدمين تسجيل الدخول إلى تطبيق الويب باستخدام حساباتهم على Google.

يمكنك أيضًا ضبط الاسم المخصّص للجمهور لتطبيقك على Friendly Chat:

8290061806aacb46.png

إعداد "مساحة التخزين في السحابة الإلكترونية" لمنصّة Firebase

يستخدم التطبيق "مساحة التخزين في السحابة الإلكترونية" لتحميل الصور.

في ما يلي كيفية إعداد ميزة "التخزين في السحابة الإلكترونية" لبرنامج Firebase في مشروعك على Firebase:

  1. في اللوحة اليسرى من وحدة تحكّم Firebase، وسِّع الإصدار، ثم اختَر مساحة التخزين.
  2. انقر على البدء.
  3. اختَر موقعًا جغرافيًا لحزمة التخزين التلقائية.
    يمكن للحِزم في US-WEST1 وUS-CENTRAL1 وUS-EAST1 الاستفادة من المستوى"مجاني دائمًا" في Google Cloud Storage. تخضع الحِزم في جميع المواقع الجغرافية الأخرى لأسعار Google Cloud Storage واستخدامها.
  4. انقر على البدء في وضع الاختبار. اقرأ بيان إخلاء المسؤولية عن قواعد الأمان.
    لا توزِّع تطبيقًا أو تعرضه للجميع بدون إضافة قواعد أمان لحزمة التخزين.
  5. انقر على إنشاء.

إضافة تطبيق ويب

في وحدة تحكّم Firebase، أضِف تطبيق ويب. لإجراء ذلك، انتقِل إلى إعدادات المشروع وانتقِل للأسفل إلى إضافة تطبيق. اختَر الويب كمنصة وضَع علامة في المربّع لإعداد ميزة "استضافة Firebase"، ثم سجِّل التطبيق وانقر على التالي لتنفيذ الخطوات المتبقية، ثم انقر على الانتقال إلى وحدة التحكّم.

4. تثبيت واجهة سطر أوامر Firebase

ستسمح لك واجهة سطر أوامر Firebase بعرض تطبيق الويب محليًا ونشر تطبيق الويب و"وظائف السحابة الإلكترونية".

لتثبيت واجهة برمجة التطبيقات أو ترقيتها، شغِّل الأمر التالي في npm:

npm -g install firebase-tools

للتأكّد من أنّه تم تثبيت واجهة برمجة التطبيقات بشكل صحيح، افتح وحدة تحكّم ونفِّذ:

firebase --version

تأكَّد من أنّ إصدار واجهة سطر أوامر Firebase أعلى من 4.0.0 لكي تتوفّر فيه جميع الميزات الحديثة المطلوبة لخدمة "وظائف السحابة الإلكترونية". إذا لم يكن الأمر كذلك، شغِّل npm install -g firebase-tools للترقية كما هو موضّح أعلاه.

عليك تفويض واجهة سطر أوامر Firebase من خلال تنفيذ ما يلي:

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. افتح هذا العنوان. من المفترض أن يظهر لك واجهة مستخدم عاملة لتطبيق محادثة.

سجِّل الدخول إلى التطبيق باستخدام الزر تسجيل الدخول باستخدام حساب Google ولا تتردد في إضافة بعض الرسائل ونشر الصور:

3b1284f5144b54f6.png

إذا سجّلت الدخول إلى التطبيق لأول مرة على متصفّح جديد، تأكَّد من السماح بالإشعارات عند ظهور طلب بذلك: 8b9d0c66dc36153d.png

سنحتاج إلى تفعيل الإشعارات في وقت لاحق.

إذا نقرت عن طريق الخطأ على حظر، يمكنك تغيير هذا الإعداد من خلال النقر على الزر 🔒 آمن على يمين عنوان URL في شريط Chrome الشامل وتبديل الشريط بجانب الإشعارات:

e926868b0546ed71.png

سنضيف الآن بعض الوظائف باستخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase في "وظائف السحابة الإلكترونية".

6- دليل الدوالّ

تتيح لك Cloud Functions إنشاء رمز برمجي يتم تشغيله بسهولة في السحابة الإلكترونية بدون الحاجة إلى إعداد خادم. سنشرح كيفية إنشاء وظائف تستجيب لأحداث قاعدة بيانات Firebase Auth وCloud Storage وFirebase Firestore. لنبدأ بـ Auth.

عند استخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase في "وظائف السحابة الإلكترونية"، سيتم وضع رمز Functions ضمن الدليل functions (تلقائيًا). رمز Functions هو أيضًا تطبيق Node.js، وبالتالي يحتاج إلى package.json يقدّم بعض المعلومات عن تطبيقك ويسرد التبعيات.

لتسهيل الأمر عليك، سبق أن أنشأنا ملف functions/index.js الذي سيتم وضع الرمز فيه. يمكنك فحص هذا الملف قبل المتابعة.

cd functions
ls

إذا لم تكن على دراية بخدمة Node.js، ننصحك بالاطّلاع على مزيد من المعلومات عنها قبل مواصلة استخدام "مختبر الرموز البرمجية".

يسرد ملف package.json حاليًا تبعيتين مطلوبتَين: حزمة تطوير البرامج (SDK) لمنصّة Firebase لخدمة "وظائف السحابة الإلكترونية" وحزمة تطوير البرامج (SDK) للمشرف في Firebase. لتثبيتها على الجهاز، انتقِل إلى مجلد 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.

سنستورد الوحدات المطلوبة ثم نكتب ثلاث دوالّ بدلاً من المهام التي يجب إكمالها. لنبدأ باستيراد وحدات Node المطلوبة.

7- استيراد وحدات "وظائف السحابة الإلكترونية" و"مشرف Firebase"

ستحتاج إلى وحدتَين خلال هذا الدليل التعليمي حول الرموز البرمجية: تتيح الوحدة firebase-functions كتابة عوامل تشغيل Cloud Functions وسجلّاتها، بينما تتيح الوحدة firebase-admin استخدام منصة Firebase على خادم يتضمّن إذن وصول مشرف لتنفيذ إجراءات مثل الكتابة إلى Cloud Firestore أو إرسال إشعارات من Firebase.

في ملف 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.

يمكن ضبط حزمة تطوير البرامج (SDK) لمشرف Firebase تلقائيًا عند نشرها في بيئة Cloud Functions أو حاويات Google Cloud Platform الأخرى، ويحدث ذلك عند استدعاء admin.initializeApp() بدون وسيطات.

الآن، لنضيف دالة يتم تنفيذها عندما يسجّل المستخدم الدخول لأول مرة في تطبيق المحادثة، وسنضيف رسالة محادثة للترحيب بالمستخدم.

8- الترحيب بالمستخدمين الجدد

بنية رسائل Chat

يتم تخزين الرسائل المنشورة في خلاصة المحادثة في FriendlyChat في Cloud Firestore. لنلقِ نظرة على بنية البيانات التي نستخدمها للرسالة. لإجراء ذلك، انشر رسالة جديدة في المحادثة نصّها "مرحبًا بك":

11f5a676fbb1a69a.png

من المفترض أن يظهر على النحو التالي:

fe6d1c020d0744cf.png

في "وحدة تحكّم Firebase"، انقر على قاعدة بيانات Firestore ضمن قسم الإنشاء. من المفترض أن تظهر لك مجموعة الرسائل ومستند واحد يحتوي على الرسالة التي كتبتها:

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، حيث يتم تخزين رسائل المحادثة.

بما أنّ هذه عملية غير متزامنة، علينا عرض الوعد الذي يشير إلى وقت انتهاء Cloud Firestore من الكتابة حتى لا يتم تنفيذ وظائف Cloud في وقت مبكر جدًا.

نشر وظائف السحابة الإلكترونية

لن تكون وظائف Cloud مفعّلة إلا بعد نشرها. لإجراء ذلك، نفِّذ ما يلي في سطر الأوامر:

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 Console Authentication وحذف حسابك من قائمة المستخدمين. بعد ذلك، سجِّل الدخول مرة أخرى.

262535d1b1223c65.png

  1. بعد تسجيل الدخول، من المفترض أن تظهر رسالة ترحيب تلقائيًا:

1c70e0d64b23525b.png

9- الإشراف على الصور

يمكن للمستخدمين تحميل جميع أنواع الصور في المحادثة، ومن المهم دائمًا الإشراف على الصور المسيئة، خاصةً في المنصات الاجتماعية العامة. في تطبيق FriendlyChat، يتم تخزين الصور التي يتم نشرها في المحادثة في حِزم Cloud Storage.

باستخدام Cloud Functions، يمكنك رصد عمليات تحميل الصور الجديدة باستخدام عامل التفعيل functions.storage().onFinalize. سيتم تنفيذ هذا الإجراء في كل مرة يتم فيها تحميل ملف جديد أو تعديله في "مساحة التخزين في السحابة الإلكترونية".

للإشراف على الصور، سننفّذ العملية التالية:

  1. تحقَّق ممّا إذا تم الإبلاغ عن الصورة على أنّها محتوى للبالغين أو محتوى عنيف باستخدام Cloud Vision API.
  2. إذا تم الإبلاغ عن الصورة، نزِّلها على مثيل Functions قيد التشغيل.
  3. تمويه الصورة باستخدام ImageMagick
  4. حمِّل الصورة المموَّهة إلى Cloud Storage.

تفعيل واجهة برمجة التطبيقات Cloud Vision API

بما أنّنا سنستخدم Google Cloud Vision API في هذه الوظيفة، عليك تفعيل واجهة برمجة التطبيقات في مشروعك على Firebase. اتّبِع هذا الرابط، ثم اختَر مشروعك على Firebase وفعِّل واجهة برمجة التطبيقات:

5c77fee51ec5de49.png

تثبيت التبعيات

للإشراف على الصور، سنستخدم مكتبة برامج Google Cloud Vision Client Library لنظام 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.

استيراد المكوّنات التابعة وضبطها

لاستيراد المكوّنات التابعة التي تم تثبيتها وبعض وحدات 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');

بما أنّ دالة Firebase Cloud Functions ستُنفَّذ داخل بيئة 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 غيغابايت من الذاكرة بدلاً من المساحة التلقائية، لأنّ هذه الدالة تستهلك ذاكرة بشكل كبير.

عند تفعيل الدالة، يتم تشغيل الصورة من خلال 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. اختَر أفضل صورة مسيئة لتحميلها (أو يمكنك استخدام هذا الزومبي آكل اللحم)، وبعد بضع لحظات، من المفترض أن تظهر مشاركة جديدة تتضمّن نسخة مموّهة من الصورة: 83dd904fbaf97d2b.png

10- إشعارات الرسائل الجديدة

في هذا القسم، ستضيف دالة Cloud Function تُرسِل إشعارات إلى المشاركين في المحادثة عند نشر رسالة جديدة.

باستخدام المراسلة عبر السحابة الإلكترونية من Firebase (FCM)، يمكنك إرسال إشعارات إلى المستخدمين على جميع المنصات بشكل موثوق. لإرسال إشعار إلى مستخدم، تحتاج إلى رمز أمان جهازه على Firebase. يجمع تطبيق الويب للمحادثة الذي نستخدمه حاليًا رموز بيانات الجهاز من المستخدمين عندما يفتحون التطبيق لأول مرة على متصفّح أو جهاز جديد. يتم تخزين هذه الرموز المميّزة في Cloud Firestore في مجموعة fcmTokens.

إذا كنت تريد معرفة كيفية الحصول على الرموز المميّزة لأجهزة "المراسلة عبر السحابة الإلكترونية من Firebase" على تطبيق ويب، يمكنك الاطّلاع على الدرس التطبيقي حول ترميز تطبيقات الويب من Firebase.

إرسال الإشعارات

لرصد وقت نشر الرسائل الجديدة، ستستخدم 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- تهانينا!

لقد استخدمت حزمة تطوير البرامج (SDK) لمنصّة Firebase في وظائف السحابة الإلكترونية وأضفت مكوّنات من جهة الخادم إلى تطبيق محادثات.

المواضيع التي تناولناها

  • إنشاء وظائف السحابة الإلكترونية باستخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase لوظائف السحابة الإلكترونية
  • يمكنك بدء وظائف السحابة الإلكترونية استنادًا إلى أحداث Auth وCloud Storage وCloud Firestore.
  • أضِف ميزة "المراسلة عبر السحابة الإلكترونية من Firebase" إلى تطبيق الويب.
  • يمكنك نشر وظائف السحابة الإلكترونية باستخدام واجهة سطر الأوامر Firebase CLI.

الخطوات التالية

مزيد من المعلومات