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

كيت جيفريز
كيت جيفريز

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

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

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

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

راجِع push-notifications-server-codelab-complete (source) للاطّلاع على الرمز الكامل.

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

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

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

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

  • نظام التشغيل macOS: Brave وEdge وSafari
  • iOS

حزمة التطبيقات

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

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

الإعداد

الحصول على نسخة قابلة للتعديل من الرمز

يُطلق على أداة تعديل الرموز التي تظهر على يسار هذه التعليمات اسم واجهة مستخدم Glitch في هذا الدرس التطبيقي حول الترميز.

  1. انقر على إنشاء ريمكس لتعديله ليصبح المشروع قابلاً للتعديل.

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

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

  1. افتح الوحدة الطرفية لتطبيق Glitch من خلال النقر على الأدوات ثم على الطرفية.
  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. أغلِق محطة Glitch.
  1. فتح "public/index.js"
  2. استبدِل VAPID_PUBLIC_KEY_VALUE_HERE بقيمة مفتاحك العام.

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

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

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

  1. لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق، ثم اضغط على ملء الشاشة ملء الشاشة.
  1. انقر على تسجيل مشغّل الخدمات في علامة التبويب التطبيق. في مربع الحالة من المفترض أن ترى رسالة مشابهة لما يلي:
Service worker registered. Scope: https://desert-cactus-sunset.glitch.me/
  1. في علامة تبويب التطبيق، انقر على الاشتراك لإرسال الإشعارات. من المحتمل أن يسألك المتصفح أو نظام التشغيل عما إذا كنت تريد السماح لموقع الويب بإرسال إشعارات فورية إليك. انقر على سماح (أو أي عبارة معادلة يستخدمها المتصفح/نظام التشغيل). في مربّع الحالة، من المفترض أن تظهر رسالة مشابهة لما يلي:
Service worker subscribed to push.  Endpoint: https://fcm.googleapis.com/fcm/send/…
  1. ارجع إلى الرمز من خلال النقر على عرض المصدر في واجهة مستخدم Glitch.
  2. افتح سجلّات Glitch بالنقر على الأدوات ثم على السجلات. من المفترض أن تظهر لك علامة /add-subscription متبوعة ببعض البيانات. /add-subscription هو عنوان URL الذي يرسل إليه العميل طلب POST عندما يريد الاشتراك في الإشعارات الفورية. البيانات التالية هي معلومات اشتراك العميل التي تحتاج إلى حفظها.
  3. فتح "server.js"
  4. عدِّل منطق معالج مسار /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. يُرجى الاطّلاع على سجلّات Glitch مرة أخرى. من المفترَض أن تظهر لك علامة /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. انقر على إلغاء الاشتراك في الإشعارات الفورية ثم انقر مرة أخرى على الاشتراك للدفع. هذا ضروري فقط لأنه، كما ذكرنا سابقًا، يعيد Glitch المشروع في كل مرة تعدّل فيها التعليمات البرمجية ويتم إعداد المشروع لحذف قاعدة البيانات عند بدء التشغيل.
  3. انقر على إعلامي. من المفترض أن تتلقّى إشعارًا فوريًا. يجب أن يكون العنوان Hello, Notifications! والنص الأساسي ID: <ID> حيث يكون <ID> رقمًا عشوائيًا.
  4. افتح التطبيق على المتصفحات أو الأجهزة الأخرى وحاول الاشتراك فيها للحصول على إشعارات فورية ثم انقر على الزر إشعار الكل. من المفترَض أن تتلقّى الإشعار نفسه على جميع الأجهزة التي اشتركت فيها (أي يجب أن يكون رقم التعريف الظاهر في نص الإشعار الأساسي متطابقًا).

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