أرسل إشعارات لتطبيق ويب باستخدام Cloud Messaging وCloud Functions

1. نظرة عامة

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

3b1284f5144b54f6.png

ما ستتعلمه

  • أنشئ وظائف Google Cloud باستخدام Firebase SDK.
  • تشغيل وظائف السحابة استنادًا إلى أحداث Auth وCloud Storage وCloud Firestore.
  • أضف دعم Firebase Cloud Messaging إلى تطبيق الويب الخاص بك.

ماذا ستحتاج

  • بطاقة ائتمان. تتطلب Cloud Functions for Firebase خطة Firebase Blaze، مما يعني أنه سيتعين عليك تمكين الفوترة على مشروع Firebase الخاص بك باستخدام بطاقة الائتمان.
  • محرر IDE/النصوص الذي تختاره مثل WebStorm أو Atom أو Sublime .
  • محطة لتشغيل أوامر shell مع تثبيت NodeJS v9.
  • متصفح مثل Chrome .
  • رمز العينة. انظر الخطوة التالية لهذا.

2. احصل على نموذج التعليمات البرمجية

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

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

قم باستيراد تطبيق البداية

باستخدام IDE الخاص بك، افتح ملف android_studio_folder.png دليل cloud-functions-start من نموذج دليل التعليمات البرمجية. يحتوي هذا الدليل على رمز البداية لبرنامج Codelab الذي يتكون من تطبيق Chat Web App الذي يعمل بكامل طاقته.

3. أنشئ مشروع Firebase وقم بإعداد تطبيقك

إنشاء مشروع

في Firebase Console ، انقر فوق "إضافة مشروع" وأطلق عليه اسم FriendlyChat .

انقر فوق إنشاء مشروع .

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

من أجل استخدام Cloud Functions لـ Firebase، سيتعين عليك ترقية مشروع Firebase الخاص بك إلى خطة فوترة Blaze . سيتطلب ذلك منك إضافة بطاقة ائتمان أو وسيلة فوترة أخرى إلى حسابك في Google Cloud.

لا تزال جميع مشاريع Firebase، بما في ذلك تلك الموجودة في خطة Blaze، تتمتع بإمكانية الوصول إلى حصص الاستخدام المجانية لوظائف السحابة. ستقع الخطوات الموضحة في هذا الدرس التطبيقي حول التعليمات البرمجية ضمن حدود استخدام الطبقة المجانية. ومع ذلك، ستلاحظ رسومًا بسيطة ( حوالي 0.03 دولارًا أمريكيًا ) من التخزين السحابي الذي يُستخدم لاستضافة صور إنشاء وظائف السحابة الخاصة بك.

إذا لم يكن لديك إمكانية الوصول إلى بطاقة الائتمان أو كنت غير مرتاح للاستمرار في خطة Blaze، ففكر في استخدام Firebase Emulator Suite الذي سيسمح لك بمحاكاة وظائف السحابة مجانًا على جهازك المحلي.

تمكين مصادقة جوجل

للسماح للمستخدمين بتسجيل الدخول إلى التطبيق، سنستخدم مصادقة Google التي يجب تمكينها.

في Firebase Console، افتح قسم البناء > المصادقة > علامة التبويب طريقة تسجيل الدخول (أو انقر هنا للانتقال إلى هناك). ثم قم بتمكين موفر تسجيل الدخول إلى Google وانقر فوق "حفظ" . سيسمح هذا للمستخدمين بتسجيل الدخول إلى تطبيق الويب باستخدام حسابات Google الخاصة بهم.

لا تتردد أيضًا في تعيين الاسم العام لتطبيقك على الدردشة الودية :

8290061806aacb46.png

تمكين التخزين السحابي

يستخدم التطبيق Cloud Storage لتحميل الصور. لتمكين Cloud Storage في مشروع Firebase الخاص بك، قم بزيارة قسم التخزين وانقر على زر البدء . اتبع الخطوات هناك، وبالنسبة لموقع التخزين السحابي، ستكون هناك قيمة افتراضية للاستخدام. انقر فوق تم بعد ذلك.

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

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

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

ستسمح لك واجهة سطر أوامر Firebase (CLI) بخدمة تطبيق الويب محليًا ونشر تطبيق الويب والوظائف السحابية.

لتثبيت أو ترقية واجهة سطر الأوامر (CLI)، قم بتشغيل الأمر npm التالي:

npm -g install firebase-tools

للتحقق من تثبيت واجهة سطر الأوامر (CLI) بشكل صحيح، افتح وحدة التحكم وقم بتشغيل:

firebase --version

تأكد من أن إصدار Firebase CLI أعلى من 4.0.0 بحيث يحتوي على أحدث الميزات المطلوبة لوظائف السحابة. إذا لم يكن الأمر كذلك، فقم بتشغيل 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. افتحه. يجب أن تشاهد واجهة المستخدم العاملة لتطبيق الدردشة.

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

3b1284f5144b54f6.png

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

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

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

e926868b0546ed71.png

سنقوم الآن بإضافة بعض الوظائف باستخدام Firebase SDK for Cloud Functions.

6. دليل الوظائف

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

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

لتسهيل الأمر عليك، قمنا بالفعل بإنشاء ملف functions/index.js حيث سيتم وضع الكود الخاص بك. لا تتردد في فحص هذا الملف قبل المضي قدما.

cd functions
ls

إذا لم تكن على دراية بـ Node.js ، فإن معرفة المزيد عنها قبل متابعة دروس البرمجة سيكون مفيدًا.

يسرد الملف package.json بالفعل اثنين من التبعيات المطلوبة: Firebase SDK for 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.

سنقوم باستيراد الوحدات المطلوبة ثم كتابة ثلاث وظائف بدلاً من المهام. لنبدأ باستيراد وحدات Node المطلوبة.

7. قم باستيراد وحدات Cloud Functions وFirebase Admin

ستكون هناك حاجة إلى وحدتين خلال هذا الدرس التطبيقي حول التعليمات البرمجية: تتيح 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. نرحب بالمستخدمين الجدد

هيكل رسائل الدردشة

يتم تخزين الرسائل المنشورة في موجز الدردشة FriendlyChat في Cloud Firestore. دعونا نلقي نظرة على بنية البيانات التي نستخدمها للرسالة. للقيام بذلك، قم بنشر رسالة جديدة في الدردشة نصها "Hello World":

11f5a676fbb1a69a.png

يجب أن يظهر هذا على النحو التالي:

fe6d1c020d0744cf.png

في Firebase Console، انقر فوق Firestore Database ضمن قسم Build . من المفترض أن تشاهد مجموعة الرسائل ومستند واحد يحتوي على الرسالة التي كتبتها:

442c9c10b5e2b245.png

كما ترى، يتم تخزين رسائل الدردشة في Cloud Firestore كمستند يحتوي على name و profilePicUrl text والطابع timestamp المضافة إلى مجموعة messages .

إضافة رسائل الترحيب

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

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

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

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

لن تكون الوظائف السحابية نشطة إلا بعد نشرها. للقيام بذلك، قم بتشغيل هذا في سطر الأوامر:

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

262535d1b1223c65.png

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

1c70e0d64b23525b.png

9. تعديل الصور

يمكن للمستخدمين تحميل جميع أنواع الصور في الدردشة، ومن المهم دائمًا تخفيف الصور المسيئة، خاصة في منصات التواصل الاجتماعي العامة. في FriendlyChat، يتم تخزين الصور التي يتم نشرها في الدردشة في Google Cloud Storage .

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

لتعديل الصور، سنمر بالعملية التالية:

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

تمكين واجهة برمجة تطبيقات Cloud Vision

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

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 الخاص بك.

استيراد وتكوين التبعيات

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

عند تشغيل الوظيفة، يتم تشغيل الصورة من خلال 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. إشعارات الرسائل الجديدة

في هذا القسم، ستضيف وظيفة سحابية ترسل إشعارات إلى المشاركين في الدردشة عند نشر رسالة جديدة.

باستخدام 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 للوظائف السحابية وأضفت مكونات من جانب الخادم إلى تطبيق الدردشة.

ما قمنا بتغطيته

  • تأليف الوظائف السحابية باستخدام Firebase SDK للوظائف السحابية.
  • تشغيل وظائف السحابة استنادًا إلى أحداث Auth وCloud Storage وCloud Firestore.
  • أضف دعم Firebase Cloud Messaging إلى تطبيق الويب الخاص بك.
  • نشر الوظائف السحابية باستخدام Firebase CLI.

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

يتعلم أكثر