12 يومًا من DigitalOcean (اليوم 4) – نشر إشعارات عيد الميلاد باستخدام وظائف DigitalOcean

مرحبًا بكم في اليوم 4 من 12 يومًا من DigitalOcean! بالأمس، أضفنا إشعارات SMS من Twilio إلى خدمة تذكير أعياد الميلاد الخاصة بنا، مما يجعلها قادرة على إرسال رسائل نصية لأعياد الميلاد اليوم. 🎂

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

مع هذا الإعداد، ستتلقى تذكيرات أعياد الميلاد حتى عندما يكون جهاز الكمبيوتر الخاص بك مغلقًا أو غير متصل بالإنترنت—ليس هناك حاجة لتشغيل البرنامج يدويًا على جهازك بعد الآن. 🎉

لماذا وظائف DigitalOcean؟

أحيانًا، كل ما تحتاجه هو نص بسيط يعمل من حين لآخر. إدارة البنية التحتية لشيء كهذا قد تكون مبالغة. هنا يأتي دور Functions. إنها منصة بدون خادم، مما يعني أنه يمكنك نشر كود يعمل فقط عند الحاجة، وتدفع فقط مقابل ما تستخدمه. مثالي لحالة الاستخدام لدينا – التحقق من أعياد الميلاد وإرسال التذكيرات يوميًا.

🚀 ما ستتعلمه

بنهاية اليوم، ستعرف كيفية:

  1. إعداد أداة doctl CLI من DigitalOcean.
  2. إنشاء والاتصال بـ namespace بدون خادم (طريقة DigitalOcean لتنظيم الوظائف).
  3. تغليف ونشر خدمة تذكير أعياد الميلاد الخاصة بك إلى DigitalOcean Functions.
  4. اختبار الوظيفة التي تم نشرها في السحابة.

🛠 ما ستحتاجه

قبل البدء، تأكد من أن لديك:

🧑‍🍳 وصفة لليوم الرابع: النشر على وظائف DigitalOcean

الخطوة 1: إعداد واجهة سطر الأوامر doctl

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

قبل أن نبدأ، دعنا نتحدث بسرعة عن doctl. إنه الأداة الرسمية لواجهة الأوامر الخاصة بـ DigitalOcean التي تتيح لك إدارة موارد السحابة الخاصة بك مباشرة من الطرفية. سنستخدمه لإنشاء مساحة اسم (مجلد لوظائفنا بدون خادم)، نشر نص بايثون الخاص بنا، واختبار الوظيفة.

إعدادها سهل:

  1. تثبيت doctl: اتبع دليل التثبيت لنظام التشغيل الخاص بك.

  2. المصادقة على doctl: قم بتوصيله بحسابك في DigitalOcean عن طريق تشغيل:

    doctl auth init
    
  3. تحقق من التثبيت: تأكد من أن كل شيء يعمل عن طريق تشغيل:

    doctl account get
    

إذا نجح الأمر، ستظهر تفاصيل عن حسابك في DigitalOcean، مثل بريدك الإلكتروني ورقم تعريف الحساب.

الخطوة 2: تثبيت برنامج السيرفرلس

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

قم بتشغيل الأمر التالي:

doctl serverless install

يمكنك التحقق من حالة التثبيت باستخدام:

doctl serverless status

إذا رأيت خطأ مثل:

Error: serverless support is installed but not connected to a functions namespace

لا تقلق—فهذا يعني فقط أننا لم نقم بإنشاء أو الاتصال بمساحة اسم بعد. سنتعامل مع ذلك في الخطوة التالية.

الخطوة 3: إنشاء والاتصال بمساحة اسم

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

  1. إنشاء مساحة أسماء جديدة:

    doctl serverless namespaces create --label "my-birthday-reminder-namespace" --region "nyc1"
    

  2. الاتصال بمساحة الأسماء:

    doctl serverless connect my-birthday-reminder-namespace
    

  3. تحقق من الاتصال:

    doctl serverless status
    

يجب أن ترى الآن تأكيدًا أنك متصل بمساحة الأسماء.

نصيحة احترافية: لرؤية قائمة بجميع المساحات المتاحة، استخدم الأمر التالي:

doctl serverless namespaces list

يمكن أن يكون هذا مفيدًا إذا كنت تدير مشاريع متعددة أو تريد التحقق من مساحة الاسم التي أنشأتها للتو.

الخطوة 4: تهيئة وإعداد هيكل المشروع

تتوقع وظائف DigitalOcean هيكل مشروع محدد للنشر بدون خادم. يمكنك بدء هذا الهيكل باستخدام doctl serverless init، أو إنشاؤه يدويًا، أو حتى استنساخ مستودع بدء التشغيل. للحفاظ على الأمور بسيطة، سنقوم بإعداده باستخدام doctl serverless init:

  1. قم بتشغيل الأمر التالي لتهيئة المشروع:

    doctl serverless init --language python birthday-reminder-service
    

    هذا ينشئ دليل مشروع محلي باسم my-birthday-reminder-service مع الهيكل الافتراضي التالي:

    my-birthday-reminder-service/
    ├── packages
    │   └── sample
    │       └── hello
    │           └── hello.py
    └── project.yml
    

  2. انتقل إلى دليل المشروع:

    cd my-birthday-reminder-service
    
  3. إعادة تسمية المجلدات لتناسب حالة الاستخدام الخاصة بنا:

    mv packages/sample packages/reminders
    mv packages/reminders/hello packages/reminders/birthdays
    mv packages/reminders/birthdays/hello.py packages/reminders/birthdays/__main__.py
    
  4. إنشاء الملفات الضرورية:

    • قم بإنشاء ملف .env فارغ في جذر المشروع:
    touch .env
    

    سيحتوي هذا الملف على بيانات اعتماد قاعدة البيانات وTwilio. سيكون الملف موجودًا في جذر مجلد my-birthday-reminder-service.

    • قم بإنشاء ملف requirements.txt في مجلد birthdays:
    touch packages/reminders/birthdays/requirements.txt
    

    سيقوم هذا الملف بسرد التبعيات الخاصة بلغة بايثون المطلوبة لوظيفتك. سيكون موجودًا تحت packages/reminders/birthdays.

    • قم بإنشاء ملف build.sh في مجلد birthdays:
    touch packages/reminders/birthdays/build.sh
    chmod +x packages/reminders/birthdays/build.sh
    

    يعتبر سكربت build.sh ضروريًا لنشر الوظائف التي تحتوي على تبعيات خارجية. يضمن أمر chmod أن يكون السكربت قابلًا للتنفيذ على أنظمة Mac/Linux.

هيكل محدث: بعد إكمال هذه الخطوات، يجب أن يبدو هيكل مشروعك كما يلي:

my-birthday-reminder-service/
├── project.yml
├── .env
├── packages
│   └── reminders
│       └── birthdays
│           ├── __main__.py
│           ├── requirements.txt
│           ├── build.sh
├── .gitignore

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

الخطوة 5: تحديث الملفات

الآن بعد أن أصبح الهيكل موجودًا، دعنا نملأه بالملفات اللازمة. افتح دليل my-birthday-reminder-service في محرر الشيفرة المفضل لديك

1. تحديث project.yml

ملف project.yml هو ملف تكوين يحدد هيكل مشروعك الخالي من الخادم، ومتغيرات البيئة، والوظائف. استبدل محتوياته بـ:

packages:
  - name: reminders
    shared: false
    environment:
      DO_DB_NAME: "${DB_NAME}"
      DO_DB_USER: "${DB_USER}"
      DO_DB_PASSWORD: "${DB_PASSWORD}"
      DO_DB_HOST: "${DB_HOST}"
      DO_DB_PORT: "${DB_PORT}"
      TWILIO_ACCOUNT_SID: "${TWILIO_ACCOUNT_SID}"
      TWILIO_AUTH_TOKEN: "${TWILIO_AUTH_TOKEN}"
      TWILIO_PHONE_FROM: "${TWILIO_PHONE_FROM}"
      TWILIO_PHONE_TO: "${TWILIO_PHONE_TO}"
    functions:
      - name: birthdays
        runtime: python:default

يقوم هذا الملف بإعداد حزمة التذكيرات ويربط متغيرات البيئة بوظائف DigitalOcean. كل متغير يتوافق مع بيانات الاعتماد المطلوبة لقاعدة البيانات الخاصة بك ودمج Twilio.

2. تحديث ملف .env الخاص بك

راجع اليوم الأول: إعداد قاعدة بيانات PostgreSQL لتذكيرات أعياد الميلاد للحصول على بيانات اعتماد قاعدة البيانات واليوم الثالث: التحقق من أعياد الميلاد وإرسال إشعارات SMS للحصول على بيانات اعتماد Twilio لملء القيم التالية:

# بيانات اعتماد قاعدة البيانات (من اليوم الأول)
DB_HOST=<your-database-hostname>
DB_NAME=<your-database-name>
DB_USER=<your-database-username>
DB_PASSWORD=<your-database-password>
DB_PORT=5432  # المنفذ الافتراضي لـ PostgreSQL

# بيانات اعتماد Twilio (من اليوم الثالث)
TWILIO_ACCOUNT_SID=<your-twilio-account-sid>
TWILIO_AUTH_TOKEN=<your-twilio-auth-token>
TWILIO_PHONE_FROM=<your-twilio-phone-number>
TWILIO_PHONE_TO=<your-personal-phone-number>

ملاحظة: يتم استخدام ملف .env لتخزين بيانات الاعتماد الحساسة بشكل آمن. سيتم قراءة هذه القيم بواسطة ملف project.yml ورسمها على البيئة الخالية من الخادم أثناء النشر، مما يجعلها متاحة لوظيفتك في السحابة.

3. إضافة التبعيات

قم بتحديث ملف requirements.txt بالتبعيات التالية:

pg8000  
python-dotenv  
twilio  

pg8000: مكتبة عميل PostgreSQL مكتوبة بلغة بايثون بالكامل.

python-dotenv: تستخدم لتحميل متغيرات البيئة من ملف .env.

twilio: مكتبة Twilio بلغة بايثون لإرسال رسائل SMS.

4. تحديث build.sh

أضف البرنامج النصي التالي إلى ملف build.sh:

#!/bin/bash
set -e

# طباعة الدليل الحالي للعمل لأغراض تصحيح الأخطاء
echo "Current working directory: $(pwd)"

# تحقق مما إذا كان ملف requirements.txt موجودًا
if [[ -f "requirements.txt" ]]; then
  echo "Found requirements.txt in $(pwd)"
else
  echo "Error: requirements.txt not found in $(pwd)"
  exit 1
fi

# إنشاء بيئة افتراضية
virtualenv --without-pip virtualenv

# تثبيت التبعات من ملف requirements.txt
pip install -r requirements.txt --target virtualenv/lib/python3.9/site-packages

هذا النص البرمجي يضمن أن جميع التبعات مُعبأة بشكل صحيح مع الدالة الخاصة بك. أمر chmod +x من الخطوة 4 يضمن أنه قابل للتنفيذ.

5. تحديث __main__.py

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

قم بتحديث ملف __main__.py بالمحتوى التالي:

# خدمة تذكير عيد الميلاد/__الرئيسية__.py

from datetime import datetime
import pg8000
from dotenv import load_dotenv
from twilio.rest import Client
import os

# تحميل متغيرات البيئة
load_dotenv()

def main(params):
    """DigitalOcean Functions entry point."""
    try:
        # الاتصال بقاعدة البيانات
        connection = pg8000.connect(
            host=os.getenv("DO_DB_HOST"),
            database=os.getenv("DO_DB_NAME"),
            user=os.getenv("DO_DB_USER"),
            password=os.getenv("DO_DB_PASSWORD"),
            port=int(os.getenv("DO_DB_PORT"))
        )
        cursor = connection.cursor()

        # الحصول على شهر اليوم ويومه
        today = datetime.now()
        today_month = today.month
        today_day = today.day

        # استعلام لاسترجاع جهات الاتصال التي يتطابق عيد ميلادها مع تاريخ اليوم
        cursor.execute(
            """
            SELECT first_name, last_name, birthday
            FROM contacts
            WHERE EXTRACT(MONTH FROM birthday) = %s
              AND EXTRACT(DAY FROM birthday) = %s;
            """,
            (today_month, today_day)
        )
        rows = cursor.fetchall()

        # الإخطار لكل جهة اتصال متطابقة
        if rows:
            account_sid = os.getenv("TWILIO_ACCOUNT_SID")
            auth_token = os.getenv("TWILIO_AUTH_TOKEN")
            client = Client(account_sid, auth_token)

            for row in rows:
                first_name, last_name, _ = row
                message = client.messages.create(
                    body=f"🎉 It's {first_name} {last_name or ''}'s birthday today! 🎂",
                    from_=os.getenv("TWILIO_PHONE_FROM"),
                    to=os.getenv("TWILIO_PHONE_TO")
                )
                print(f"Message sent for {first_name} {last_name}. Message SID: {message.sid}")
        else:
            print("No birthdays today.")

        # إغلاق المؤشر والاتصال
        cursor.close()
        connection.close()

    except Exception as e:
        print(f"An error occurred: {e}")

إليك ما قمنا بتغييره:

  1. تمت إضافة دالة main(params): تتوقع وظائف DigitalOcean نقطة دخول دالة باسم main، والتي تأخذ وسيط params. هنا تبدأ الدالة في التنفيذ.

  2. تم نقل منطق البرنامج النصي داخل دالة main:
    لقد تم لف الكود من اليوم الثالث داخل دالة main لتلبية هذا المتطلب.

  3. كل شيء آخر يبقى كما هو:
    منطق اتصال قاعدة البيانات، والتحقق من أعياد الميلاد، ومنطق إشعارات الرسائل القصيرة لم يتغير.

الخطوة 5: تعبئة ونشر

مع وجود كل شيء في مكانه، قم بنشر مشروعك إلى وظائف DigitalOcean:

  1. نشر المشروع:
doctl serverless deploy my-birthday-reminder-service

للتحقق من أن وظيفتك قد تم نشرها بنجاح إلى النطاق:

  1. قم بزيارة لوحة التحكم في DigitalOcean، وانتقل إلى وظائف في الشريط الجانبي الأيسر.
  2. حدد نطاقك (على سبيل المثال، my-birthday-reminder-namespace).
  3. تحقق من أن وظيفتك تظهر تحت النطاق، والتي تُدرج عادةً كـ reminders/birthdays.
  4. انقر على اسم الوظيفة لعرض التفاصيل، بما في ذلك السجلات، والتكوين، وتاريخ الاستدعاء.

الخطوة 6: اختبار وظيفتك المنشورة

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

الخيار 1: استخدام واجهة سطر الأوامر DigitalOcean

doctl serverless functions invoke reminders/birthdays

إذا تم إعداد كل شيء بشكل صحيح، ستعمل دالتك في السحابة، تتحقق من أعياد الميلاد اليوم وترسل إشعارات عبر الرسائل القصيرة.

![https://doimages.nyc3.cdn.digitaloceanspaces.com/006Community/12-Days-of-DO/Postgressql-birthday/birthday_reminder_service_text_message.jpeg]

الخيار 2: استخدام لوحة تحكم DigitalOcean

  1. اذهب إلى لوحة تحكم DigitalOcean.
  2. انتقل إلى الدوال وابحث عن دالتك الخاصة بالتذكيرات/أعياد الميلاد.
  3. اضغط على تشغيل لتشغيلها يدويًا.
  4. عرض المخرجات والسجلات مباشرة في وحدة التحكم.

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

نصائح للاختبار

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

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

🎁 ملخص

إليك ما حققناه اليوم:

✅ إعداد doctl وإنشاء مساحة اسم لمشروعنا.
✅ إعادة هيكلة سكربت بايثون للنشر.
✅ تعبئة ونشر خدمة تذكير أعياد الميلاد إلى خدمات DigitalOcean.
✅ اختبار الدالة في السحابة باستخدام كل من سطر الأوامر ولوحة تحكم DigitalOcean.

التالي: بينما تعتبر هذه خطوة كبيرة إلى الأمام، لا نزال نشغل الدالة يدويًا. في المنشور التالي، سنقوم بأتمتة هذه العملية بحيث تعمل خدمة تذكير أعياد الميلاد تلقائيًا كل يوم في وقت محدد. تخيل الاستيقاظ على تذكير نصي دون رفع إصبع—دعنا نجعل ذلك يحدث غدًا! 🚀

Source:
https://www.digitalocean.com/community/tutorials/deploying-birthday-notifications-with-digitalocean-functions