درس تطبيقي حول الترميز: إنشاء خادم إشعارات فورية

Kate Jeffreys
Kate Jeffreys
Kayce Basques
Kayce Basques

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

  • تتبُّع اشتراكات الإشعارات الفورية (أي أنّ الخادم ينشئ سجلّ قاعدة بيانات جديدًا عندما يوافق العميل على تلقّي الإشعارات الفورية، ويحذف سجلّ قاعدة بيانات حاليًا عندما يرفض العميل تلقّيها)
  • إرسال إشعار فوري إلى عميل واحد
  • إرسال إشعار فوري إلى جميع العملاء المشتركين

يركّز هذا الدرس العملي على مساعدتك في التعلّم من خلال الممارسة ولا يتناول الكثير من المفاهيم. اطّلِع على مقالة كيف تعمل الإشعارات الفورية؟ للتعرّف على مفاهيم الإشعارات الفورية.

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

توافُق المتصفح

من المعروف أنّ هذا الدرس التطبيقي العملي يعمل مع المجموعات التالية من أنظمة التشغيل والمتصفّحات:

  • ‫Windows: Chrome وEdge
  • ‫macOS: Chrome وFirefox
  • ‫Android: Chrome وFirefox

من المعروف أنّ هذا الدرس العملي لا يعمل مع أنظمة التشغيل التالية (أو مجموعات نظام التشغيل والمتصفح):

  • ‫macOS: Brave وEdge وSafari
  • iOS

حزمة التطبيق

  • تم إنشاء الخادم باستخدام Express.js.
  • تتولّى مكتبة web-push Node.js معالجة جميع منطق الإشعارات الفورية.
  • تتم كتابة بيانات الاشتراك في ملف JSON باستخدام lowdb.

لست مضطرًا إلى استخدام أيّ من هذه التقنيات لتنفيذ الإشعارات الفورية. اخترنا هذه التقنيات لأنّها توفّر تجربة موثوقة في استخدام Codelab.

الإعداد

إعداد المصادقة

قبل أن تتمكّن من تفعيل الإشعارات الفورية، عليك إعداد الخادم والعميل باستخدام مفاتيح المصادقة. اطّلِع على توقيع طلبات بروتوكول الإشعارات الفورية على الويب لمعرفة السبب.

  1. افتح الوحدة الطرفية.
  2. في الوحدة الطرفية، شغِّل npx web-push generate-vapid-keys. انسخ قيم المفتاح الخاص والمفتاح العام.
  3. افتح .env وعدِّل VAPID_PUBLIC_KEY وVAPID_PRIVATE_KEY. اضبط قيمة VAPID_SUBJECT على mailto:test@test.test. يجب وضع كل هذه القيم بين علامات اقتباس مزدوجة. بعد إجراء التعديلات، من المفترض أن يبدو ملف .env على النحو التالي:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  1. فتح "public/index.js"
  2. استبدِل VAPID_PUBLIC_KEY_VALUE_HERE بقيمة مفتاحك العام.

إدارة الاشتراكات

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

حفظ معلومات الاشتراك الجديدة

  1. انقر على تسجيل عامل الخدمة في علامة تبويب التطبيق. في مربّع الحالة، من المفترض أن تظهر لك رسالة مشابهة لما يلي:
Service worker registered. Scope: https://example.com
  1. في علامة تبويب التطبيق، انقر على الاشتراك في الإشعارات الفورية. من المحتمل أن يطلب منك المتصفّح أو نظام التشغيل تحديد ما إذا كنت تريد السماح للموقع الإلكتروني بإرسال إشعارات فورية إليك. انقر على السماح (أو أي عبارة مكافئة يستخدمها المتصفّح أو نظام التشغيل). في مربّع الحالة، من المفترض أن تظهر لك رسالة مشابهة لما يلي:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
  1. افتح الوحدة الطرفية للاطّلاع على السجلّات. يجب أن يظهر لك /add-subscription متبوعًا ببعض البيانات. /add-subscription هو عنوان URL الذي يرسل إليه العميل طلب POST عندما يريد الاشتراك في خدمة الإشعارات الفورية. البيانات التالية هي معلومات اشتراك العميل التي عليك حفظها.
  2. فتح "server.js"
  3. عدِّل منطق معالج مسار /add-subscription باستخدام الرمز التالي:
app.post('/add-subscription', (request, response) => {
  console.log('/add-subscription');
  console.log(request.body);
  console.log(`Subscribing ${request.body.endpoint}`);
  db.get('subscriptions')
    .push(request.body)
    .write();
  response.sendStatus(200);
});

حذف معلومات الاشتراك القديمة

  1. ارجع إلى علامة تبويب التطبيق.
  2. انقر على إلغاء الاشتراك في الإشعارات الفورية.
  3. ألقِ نظرة على السجلّات مرة أخرى. من المفترض أن يظهر /remove-subscription متبوعًا بمعلومات اشتراك العميل.
  4. عدِّل منطق معالج مسار /remove-subscription باستخدام الرمز التالي:
app.post('/remove-subscription', (request, response) => {
  console.log('/remove-subscription');
  console.log(request.body);
  console.log(`Unsubscribing ${request.body.endpoint}`);
  db.get('subscriptions')
    .remove({endpoint: request.body.endpoint})
    .write();
  response.sendStatus(200);
});

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

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

  1. عدِّل منطق معالج مسار /notify-me باستخدام الرمز التالي:
app.post('/notify-me', (request, response) => {
  console.log('/notify-me');
  console.log(request.body);
  console.log(`Notifying ${request.body.endpoint}`);
  const subscription = 
      db.get('subscriptions').find({endpoint: request.body.endpoint}).value();
  sendNotifications([subscription]);
  response.sendStatus(200);
});
  1. عدِّل الدالة sendNotifications() باستخدام الرمز التالي:
function sendNotifications(subscriptions) {
  // TODO
  // Create the notification content.
  const notification = JSON.stringify({
    title: "Hello, Notifications!",
    options: {
      body: `ID: ${Math.floor(Math.random() * 100)}`
    }
  });
  // Customize how the push service should attempt to deliver the push message.
  // And provide authentication information.
  const options = {
    TTL: 10000,
    vapidDetails: vapidDetails
  };
  // Send a push message to each client specified in the subscriptions array.
  subscriptions.forEach(subscription => {
    const endpoint = subscription.endpoint;
    const id = endpoint.substr((endpoint.length - 8), endpoint.length);
    webpush.sendNotification(subscription, notification, options)
      .then(result => {
        console.log(`Endpoint ID: ${id}`);
        console.log(`Result: ${result.statusCode}`);
      })
      .catch(error => {
        console.log(`Endpoint ID: ${id}`);
        console.log(`Error: ${error} `);
      });
  });
}
  1. عدِّل منطق معالج مسار /notify-all باستخدام الرمز التالي:
app.post('/notify-all', (request, response) => {
  console.log('/notify-all');
  response.sendStatus(200);
  console.log('Notifying all subscribers');
  const subscriptions =
      db.get('subscriptions').cloneDeep().value();
  if (subscriptions.length > 0) {
    sendNotifications(subscriptions);
    response.sendStatus(200);
  } else {
    response.sendStatus(409);
  }
});
  1. ارجع إلى علامة تبويب التطبيق.
  2. انقر على إرسال إشعار إليّ. من المفترض أن تتلقّى إشعارًا فوريًا. يجب أن يكون العنوان Hello, Notifications! والنص ID: <ID>، حيث <ID> هو رقم عشوائي.
  3. افتح تطبيقك على متصفحات أو أجهزة أخرى وحاوِل الاشتراك في الإشعارات الفورية ثم انقر على الزر إرسال إشعار إلى الجميع. يجب أن تتلقّى الإشعار نفسه على جميع أجهزتك التي اشتركت فيها (أي يجب أن يكون رقم التعريف في نص الإشعار الفوري هو نفسه).

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