دليل شامل: بناء بوت ديسكورد احترافي بلغة بايثون واستضافته مجانًا

دقائق القراءة: 17

مقدمة: بناء بوت ديسكورد سحابي مجاني بالكامل

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

كيفية إنشاء حساب بوت ديسكورد خاص بك

للبدء في العمل مع مكتبة بايثون وواجهة Discord API، يجب علينا أولاً إنشاء حساب بوت ديسكورد. إليك الخطوات اللازمة لإنشاء حساب البوت:

صورة توضح زر "New Application" لإنشاء تطبيق جديد في ديسكورد.

  • امنح التطبيق اسمًا مناسبًا ثم انقر على “Create“.

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

  • اذهب إلى تبويب “Bot” ثم انقر على “Add Bot“. سيتعين عليك التأكيد بالنقر على “Yes, do it!“.

صورة توضح تبويب "Bot" وزر "Add Bot" في إعدادات تطبيق ديسكورد.

  • احتفظ بالإعدادات الافتراضية لـ Public Bot (محدد) و Require OAuth2 Code Grant (غير محدد). لقد تم إنشاء البوت الخاص بك بنجاح. الخطوة التالية هي نسخ الرمز المميز (token).

صورة توضح الرمز المميز (token) الخاص بالبوت في ديسكورد.

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

كيفية دعوة البوت للانضمام إلى خادم ديسكورد

الآن بعد أن أنشأت البوت، حان الوقت لإدخاله إلى خادم. للقيام بذلك، يجب عليك إنشاء رابط دعوة (invite URL) خاص به.

  • انتقل إلى تبويب “OAuth2“.
  • ثم اختر “bot” ضمن قسم “scopes“.

صورة توضح تبويب "OAuth2" واختيار "bot" ضمن "scopes" في ديسكورد.

  • الآن اختر الأذونات (permissions) التي تريدها للبوت. سيستخدم البوت الخاص بنا بشكل أساسي الرسائل النصية، لذا لا نحتاج إلى الكثير من الأذونات. قد تحتاج إلى المزيد حسب وظيفة بوتك. كن حذرًا عند اختيار إذن “Administrator“.

صورة توضح اختيار الأذونات المطلوبة لبوت ديسكورد.

  • بعد تحديد الأذونات المناسبة، انقر على زر “copy” الموجود فوق الأذونات. سيؤدي ذلك إلى نسخ رابط URL يمكن استخدامه لإضافة البوت إلى خادم.
  • الصق الرابط في متصفحك، اختر الخادم الذي تريد دعوة البوت إليه، ثم انقر على “Authorize“.
  • لإضافة البوت، يجب أن يكون لحسابك أذونات “Manage Server“.

الآن بعد أن أنشأت مستخدم البوت، سنبدأ في كتابة كود بايثون الخاص به.

برمجة بوت ديسكورد أساسي باستخدام مكتبة discord.py

سنستخدم مكتبة بايثون discord.py لكتابة كود البوت. discord.py هي غلاف (API wrapper) لواجهة Discord API يجعل إنشاء بوت ديسكورد في بايثون أسهل.

إنشاء Repl وتثبيت مكتبة discord.py

يمكنك تطوير البوت على جهازك المحلي باستخدام أي محرر أكواد. ومع ذلك، في هذا الدليل، سنستخدم Repl.it لأنه سيجعل الأمر أبسط لأي شخص يرغب في المتابعة. Repl.it هو بيئة تطوير متكاملة (IDE) عبر الإنترنت يمكنك استخدامها في متصفح الويب الخاص بك.

  • ابدأ بالانتقال إلى Repl.it.
  • أنشئ Repl جديدًا واختر “Python” كلغة.
  • لاستخدام مكتبة discord.py، ما عليك سوى كتابة import discord في الجزء العلوي من ملف main.py. سيقوم Repl.it تلقائيًا بتثبيت هذه التبعية عند النقر على زر “run“.
  • إذا كنت تفضل برمجة البوت محليًا، يمكنك استخدام هذا الأمر على نظام MacOS لتثبيت discord.py:
python3 -m pip install -U discord.py
  • قد تضطر إلى استخدام pip3 بدلاً من pip.
  • إذا كنت تستخدم نظام Windows، فيجب عليك استخدام السطر التالي بدلاً من ذلك:
py -3 -m pip install -U discord.py

إعداد الأحداث (Events) لبوت ديسكورد

تتمحور مكتبة discord.py حول مفهوم الأحداث (events). الحدث هو شيء تستمع إليه ثم تستجيب له. على سبيل المثال، عندما تحدث رسالة، ستتلقى حدثًا بشأنها يمكنك الاستجابة له. دعنا ننشئ بوتًا يرد على رسالة محددة. كود البوت البسيط هذا، بالإضافة إلى شرح الكود، مأخوذ من وثائق discord.py. سنضيف المزيد من الميزات إلى البوت لاحقًا. أضف هذا الكود إلى ملف main.py. (يمكنك تسمية الملف بأي شيء آخر إذا أردت، فقط ليس discord.py.) سأشرح ما يفعله هذا الكود قريبًا.

import discord
import os

client = discord.Client()

@client.event
async def on_ready():
    print('We have logged in as {0.user}'.format(client))

@client.event
async def on_message(message):
    if message.author == client.user:
        return

    if message.content.startswith('$hello'):
        await message.channel.send('Hello!')

client.run(os.getenv('TOKEN'))

عندما أنشأت مستخدم البوت الخاص بك على ديسكورد، قمت بنسخ رمز مميز (token). الآن سنقوم بإنشاء ملف .env لتخزين الرمز المميز. إذا كنت تقوم بتشغيل الكود محليًا، فلن تحتاج إلى ملف .env. ما عليك سوى استبدال os.getenv('TOKEN') بالرمز المميز مباشرةً. تُستخدم ملفات .env لتصريح متغيرات البيئة (environment variables). في Repl.it، تكون معظم الملفات التي تنشئها مرئية للجميع، ولكن ملفات .env تكون مرئية لك فقط. لن يتمكن الأشخاص الآخرون الذين يشاهدون repl عامًا من رؤية محتويات ملف .env. لذا، إذا كنت تقوم بالتطوير على Repl.it، قم فقط بتضمين المعلومات الخاصة مثل الرموز المميزة أو المفاتيح في ملف .env.

  • انقر على زر “Add file” وأنشئ ملفًا باسم .env.

صورة توضح كيفية إضافة ملف جديد باسم .env في Repl.it.

  • داخل الملف، أضف السطر التالي، متضمنًا الرمز المميز الفعلي الذي نسخته سابقًا:
TOKEN=[paste token here]

الآن دعنا نراجع ما يفعله كل سطر من الكود في كود بوت ديسكورد الخاص بك.

  • السطر الأول يستورد مكتبة discord.py.
  • السطر الثاني يستورد مكتبة os، ولكن هذا يُستخدم فقط للحصول على متغير TOKEN من ملف .env. إذا لم تكن تستخدم ملف .env، فلن تحتاج إلى هذا السطر.
  • بعد ذلك، ننشئ نسخة من Client. هذا هو الاتصال بخادم ديسكورد.
  • يُستخدم المزخرف (decorator) @client.event() لتسجيل حدث. هذه مكتبة غير متزامنة (asynchronous)، لذا تتم الأمور باستخدام دوال الاستدعاء (callbacks). دالة الاستدعاء هي دالة يتم استدعاؤها عندما يحدث شيء آخر. في هذا الكود، يتم استدعاء حدث on_ready() عندما يكون البوت جاهزًا للبدء في الاستخدام.
  • ثم، عندما يتلقى البوت رسالة، يتم استدعاء حدث on_message().
  • يتم تشغيل حدث on_message() في كل مرة يتم فيها تلقي رسالة، ولكننا لا نريد أن يفعل أي شيء إذا كانت الرسالة من البوت نفسه. لذا، إذا كان Message.author هو نفسه Client.user، فإن الكود يعود ببساطة.
  • بعد ذلك، نتحقق مما إذا كان Message.content يبدأ بـ '$hello'. إذا كان الأمر كذلك، فإن البوت يرد بـ 'Hello!' على القناة التي استخدم فيها.
  • الآن بعد أن تم إعداد البوت، يقوم السطر الأخير بتشغيل البوت باستخدام رمز تسجيل الدخول. يحصل على الرمز المميز من ملف .env الخاص بنا. لدينا الكود الخاص بالبوت، لذا علينا الآن تشغيله.

تشغيل بوت ديسكورد

الآن انقر على زر “run” في الأعلى لتشغيل البوت الخاص بك في repl.it. إذا كنت تكتب البوت محليًا، يمكنك استخدام هذه الأوامر في الطرفية (terminal) لتشغيل البوت:

  • على نظام Windows:
py -3 main.py
  • على الأنظمة الأخرى:
python3 main.py

الآن اذهب إلى غرفة ديسكورد الخاصة بك واكتب “$hello“. يجب أن يرد البوت بـ “Hello!“.

صورة توضح رد البوت بـ "Hello!" في ديسكورد.

تحسين بوت ديسكورد وإضافة ميزات جديدة

الآن بعد أن أصبح لدينا بوت أساسي يعمل، سنقوم بتحسينه. يُسمى هذا البوت “Encourage Bot” لسبب وجيه. سيستجيب هذا البوت برسالة تشجيعية عندما يرسل شخص ما رسالة تحتوي على كلمة حزينة أو محبطة. سيتمكن أي شخص من إضافة رسائل تشجيعية ليستخدمها البوت، وسيتم تخزين الرسائل التي يرسلها المستخدمون في قاعدة بيانات Repl.it. سيعيد البوت أيضًا اقتباسًا ملهمًا عشوائيًا من واجهة برمجة تطبيقات (API) عندما يكتب شخص ما الرسالة “$inspire” في الدردشة. سنبدأ بإضافة ميزة “$inspire“.

إضافة اقتباسات ملهمة إلى البوت

سنحصل على اقتباسات ملهمة من واجهة برمجة تطبيقات تسمى zenquotes.io. نحتاج إلى استيراد وحدتين إضافيتين من بايثون، وإضافة دالة get_quote()، وتحديث كود البوت الخاص بنا لاستدعاء الدالة. إليك الكود المحدث. بعد الكود، سأشرح الأجزاء الجديدة.

import discord
import os
import requests
import json

client = discord.Client()

def get_quote():
    response = requests.get("https://zenquotes.io/api/random")
    json_data = json.loads(response.text)
    quote = json_data[0]['q'] + " -" + json_data[0]['a']
    return(quote)

@client.event
async def on_ready():
    print('We have logged in as {0.user}'.format(client))

@client.event
async def on_message(message):
    if message.author == client.user:
        return

    if message.content.startswith('$inspire'):
        quote = get_quote()
        await message.channel.send(quote)

client.run(os.getenv('TOKEN'))

الآن يجب علينا استيراد وحدة requests. تسمح هذه الوحدة لكودنا بتقديم طلب HTTP للحصول على بيانات من واجهة برمجة التطبيقات. تُرجع واجهة برمجة التطبيقات بيانات بتنسيق JSON، لذا فإن وحدة json تجعل العمل مع البيانات المرتجعة أسهل.

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

بعد ذلك داخل الدالة، نستخدم json.loads() لتحويل الاستجابة من واجهة برمجة التطبيقات إلى تنسيق JSON. من خلال التجربة والخطأ، اكتشفت كيفية الحصول على الاقتباس من JSON بالتنسيق النصي الذي أردته. يتم إرجاع الاقتباس من الدالة كسلسلة نصية (string).

الجزء الأخير المحدث في الكود هو في النهاية. سابقًا، كان يبحث عن رسالة تبدأ بـ “$hello“. الآن يبحث عن “$inspire“. وبدلاً من إرجاع “Hello!“، فإنه يحصل على الاقتباس باستخدام quote = get_quote() ويعيد الاقتباس. في هذه المرحلة، يمكنك تشغيل الكود الخاص بك وتجربته.

إضافة رسائل تشجيعية إلى البوت

الآن سنقوم بتنفيذ الميزة التي يستجيب فيها البوت برسائل تشجيعية عندما ينشر المستخدم رسالة تحتوي على كلمة حزينة.

إضافة الكلمات الدالة على الحزن إلى البوت

أولاً، نحتاج إلى إنشاء قائمة بايثون (Python list) تحتوي على الكلمات الحزينة التي سيستجيب لها البوت. أضف السطر التالي بعد إنشاء متغير client:

sad_words = ["sad", "depressed", "unhappy", "angry", "miserable"]

لا تتردد في إضافة المزيد من الكلمات إلى القائمة.

تضمين قائمة الرسائل التشجيعية

الآن سنضيف قائمة بالرسائل التشجيعية التي سيرد بها البوت. أضف القائمة التالية بعد قائمة sad_words التي أنشأتها:

starter_encouragements = [
  "Cheer up!",
  "Hang in there.",
  "You are a great person / bot!"
]

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

تحديث دالة الاستجابة للرسائل (on_message)

الآن نحتاج إلى تحديث البوت الخاص بنا لاستخدام القائمتين اللتين أنشأناهما. أولاً، استورد وحدة random لأن البوت سيختار رسائل تشجيعية عشوائيًا. أضف السطر التالي إلى عبارات الاستيراد في الجزء العلوي من الكود: import random. الآن سنقوم بتحديث دالة on_message() للتحقق من جميع الرسائل لمعرفة ما إذا كانت تحتوي على كلمة من قائمة sad_words. إذا تم العثور على كلمة حزينة، سيرسل البوت رسالة تشجيع عشوائية. إليك الكود المحدث:

async def on_message(message):
    if message.author == client.user:
        return

    msg = message.content

    if msg.startswith('$inspire'):
        quote = get_quote()
        await message.channel.send(quote)

    if any(word in msg for word in sad_words):
        await message.channel.send(random.choice(starter_encouragements))

هذا وقت جيد لاختبار البوت. أنت تعرف الآن ما يكفي لإنشاء بوت خاص بك. ولكن بعد ذلك ستتعلم كيفية تنفيذ ميزات أكثر تقدمًا وتخزين البيانات باستخدام قاعدة بيانات Repl.it.

تمكين إضافة رسائل تشجيعية من قبل المستخدمين

البوت يعمل بكامل طاقته، ولكن دعنا الآن نجعل من الممكن تحديث البوت مباشرة من ديسكورد. يجب أن يتمكن المستخدم من إضافة المزيد من الرسائل التشجيعية ليستخدمها البوت عندما يكتشف كلمة حزينة. سنستخدم قاعدة بيانات Repl.it المدمجة لتخزين الرسائل التي يرسلها المستخدمون. قاعدة البيانات هذه هي مخزن قيم مفتاحية (key-value store) مدمج في كل repl.

في الجزء العلوي من الكود، تحت عبارات الاستيراد الأخرى، أضف from replit import db. سيسمح لنا هذا باستخدام قاعدة بيانات Repl.it. سيتمكن المستخدمون من إضافة رسائل تشجيعية مخصصة ليستخدمها البوت مباشرة من دردشة ديسكورد. قبل أن نضيف أوامر جديدة للبوت، دعنا ننشئ دالتين مساعدتين (helper functions) ستضيفان الرسائل المخصصة إلى قاعدة البيانات وتحذفانها.

أضف الكود التالي بعد دالة get_quote():

def update_encouragements(encouraging_message):
    if "encouragements" in db.keys():
        encouragements = db["encouragements"]
        encouragements.append(encouraging_message)
        db["encouragements"] = encouragements
    else:
        db["encouragements"] = [encouraging_message]

def delete_encouragment(index):
    encouragements = db["encouragements"]
    if len(encouragements) > index:
        del encouragements[index]
    db["encouragements"] = encouragements

تستقبل دالة update_encouragements() رسالة تشجيعية كمعامل (argument). أولاً، تتحقق مما إذا كانت “encouragements” مفتاحًا في قاعدة البيانات. إذا كان الأمر كذلك، فإنها تحصل على قائمة التشجيعات الموجودة بالفعل في قاعدة البيانات، وتضيف الرسالة الجديدة إلى القائمة، وتخزن القائمة المحدثة مرة أخرى في قاعدة البيانات تحت مفتاح “encouragements“. إذا لم تكن قاعدة البيانات تحتوي بالفعل على “encouragements“، يتم إنشاء مفتاح جديد بهذا الاسم وتضاف الرسالة التشجيعية الجديدة كأول عنصر في القائمة.

تستقبل دالة delete_encouragement() فهرسًا (index) كمعامل. تحصل على قائمة التشجيعات من قاعدة البيانات المخزنة تحت مفتاح “encouragements“. إذا كان عدد العناصر في قائمة التشجيعات أكبر من الفهرس، يتم حذف عنصر القائمة في ذلك الفهرس. أخيرًا، يتم تخزين القائمة المحدثة مرة أخرى في قاعدة البيانات تحت مفتاح “encouragements“.

إليك الكود المحدث لدالة on_message(). بعد الكود، سأشرح الأقسام الجديدة.

async def on_message(message):
    if message.author == client.user:
        return

    msg = message.content

    if msg.startswith("$inspire"):
        quote = get_quote()
        await message.channel.send(quote)

    options = starter_encouragements
    if "encouragements" in db.keys():
        options = options + db["encouragements"]

    if any(word in msg for word in sad_words):
        await message.channel.send(random.choice(options))

    if msg.startswith("$new"):
        encouraging_message = msg.split("$new ", 1)[1]
        update_encouragements(encouraging_message)
        await message.channel.send("New encouraging message added.")

    if msg.startswith("$del"):
        encouragements = []
        if "encouragements" in db.keys():
            index = int(msg.split("$del", 1)[1])
            delete_encouragment(index)
            encouragements = db["encouragements"]
        await message.channel.send(encouragements)

السطر الجديد الأول من الكود أعلاه هو options = starter_encouragements. نحن ننشئ نسخة من starter_encouragements لأننا سنضيف الرسائل التي يرسلها المستخدمون إلى تلك القائمة قبل اختيار رسالة عشوائية ليرسلها البوت. نتحقق مما إذا كانت “encouragements” موجودة بالفعل في مفاتيح قاعدة البيانات (مما يعني أن المستخدم قد أرسل رسالة مخصصة واحدة على الأقل). إذا كان الأمر كذلك، نضيف رسائل المستخدم إلى التشجيعات الأولية. ثم، بدلاً من إرسال رسالة عشوائية من starter_encouragements، يرسل البوت الآن رسالة عشوائية من options.

القسم الجديد التالي من الكود يستخدم لإضافة رسالة جديدة يرسلها المستخدم إلى قاعدة البيانات. إذا بدأت رسالة ديسكورد بـ “$new“، فسيتم استخدام النص بعد “$new” كرسالة تشجيعية جديدة. يقوم الكود msg.split("$new ",1)[1] بفصل الرسالة عن الأمر “$new” ويخزن الرسالة في متغير. في هذا السطر من الكود، لاحظ المسافة في “$new “. نريد كل شيء بعد المسافة. نستدعي الدالة المساعدة update_encouragements بالرسالة الجديدة، ثم يرسل البوت رسالة إلى دردشة ديسكورد تؤكد إضافة الرسالة.

القسم الجديد الثالث (في نهاية الكود أعلاه) يتحقق مما إذا كانت رسالة ديسكورد جديدة تبدأ بـ “$del“. هذا هو الأمر لحذف عنصر من قائمة “encouragements” في قاعدة البيانات. أولاً، يتم تهيئة متغير جديد يسمى encouragements كمصفوفة فارغة (empty array). والسبب في ذلك هو أن هذا القسم من الكود سيرسل رسالة بمصفوفة فارغة إذا لم تتضمن قاعدة البيانات مفتاح “encouragement“. إذا كان مفتاح “encouragement” موجودًا في قاعدة البيانات، فسيتم فصل الفهرس عن رسالة ديسكورد التي تبدأ بـ “$del“. ثم يتم استدعاء دالة delete_encouragement() مع تمرير الفهرس المراد حذفه. يتم تحميل القائمة المحدثة للتشجيعات في متغير encouragements، ثم يرسل البوت رسالة إلى ديسكورد بالقائمة الحالية.

الميزات النهائية لبوت ديسكورد

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

import discord
import os
import requests
import json
import random
from replit import db

client = discord.Client()

sad_words = ["sad", "depressed", "unhappy", "angry", "miserable"]

starter_encouragements = [
    "Cheer up!",
    "Hang in there.",
    "You are a great person / bot!"
]

if "responding" not in db.keys():
    db["responding"] = True

def get_quote():
    response = requests.get("https://zenquotes.io/api/random")
    json_data = json.loads(response.text)
    quote = json_data[0]["q"] + " -" + json_data[0]["a"]
    return(quote)

def update_encouragements(encouraging_message):
    if "encouragements" in db.keys():
        encouragements = db["encouragements"]
        encouragements.append(encouraging_message)
        db["encouragements"] = encouragements
    else:
        db["encouragements"] = [encouraging_message]

def delete_encouragment(index):
    encouragements = db["encouragements"]
    if len(encouragements) > index:
        del encouragements[index]
    db["encouragements"] = encouragements

@client.event
async def on_ready():
    print("We have logged in as {0.user}".format(client))

@client.event
async def on_message(message):
    if message.author == client.user:
        return

    msg = message.content

    if msg.startswith("$inspire"):
        quote = get_quote()
        await message.channel.send(quote)

    if db["responding"]:
        options = starter_encouragements
        if "encouragements" in db.keys():
            options = options + db["encouragements"]

        if any(word in msg for word in sad_words):
            await message.channel.send(random.choice(options))

    if msg.startswith("$new"):
        encouraging_message = msg.split("$new ", 1)[1]
        update_encouragements(encouraging_message)
        await message.channel.send("New encouraging message added.")

    if msg.startswith("$del"):
        encouragements = []
        if "encouragements" in db.keys():
            index = int(msg.split("$del", 1)[1])
            delete_encouragment(index)
            encouragements = db["encouragements"]
        await message.channel.send(encouragements)

    if msg.startswith("$list"):
        encouragements = []
        if "encouragements" in db.keys():
            encouragements = db["encouragements"]
        await message.channel.send(encouragements)

    if msg.startswith("$responding"):
        value = msg.split("$responding ", 1)[1]
        if value.lower() == "true":
            db["responding"] = True
            await message.channel.send("Responding is on.")
        else:
            db["responding"] = False
            await message.channel.send("Responding is off.")

client.run(os.getenv("TOKEN"))

القسم الأول الذي أضيف إلى الكود هو أسفل قائمة starter_encouragements مباشرةً:

if "responding" not in db.keys():
    db["responding"] = True

ننشئ مفتاحًا جديدًا في قاعدة البيانات يسمى “responding” ونضبط قيمته على “True“. سنستخدم هذا لتحديد ما إذا كان البوت يجب أن يستجيب للكلمات الحزينة أم لا. نظرًا لأن قاعدة البيانات تُحفظ حتى بعد توقف البرنامج عن العمل، فإننا ننشئ المفتاح الجديد فقط إذا لم يكن موجودًا بالفعل.

الجزء الجديد التالي من الكود هو أن القسم الذي يستجيب للكلمات الحزينة أصبح الآن داخل جملة if هذه: if db["responding"]:. سيستجيب البوت للكلمات الحزينة فقط إذا كانت db["responding"] = True. القدرة على تحديث هذه القيمة تأتي بعد هذا القسم التالي.

بعد ذلك، بعد الكود الذي يجعل البوت يستجيب لأمر “$del“، يوجد كود جديد للاستجابة لأمر “$list” عند إرساله كرسالة ديسكورد. يبدأ هذا القسم بإنشاء قائمة فارغة تسمى encouragements. ثم، إذا كانت هناك بالفعل تشجيعات في قاعدة البيانات، فإن تلك التشجيعات تحل محل القائمة الفارغة التي تم إنشاؤها للتو. أخيرًا، يرسل البوت قائمة التشجيعات كرسالة ديسكورد.

القسم الجديد الأخير يأتي بعد ذلك. هذا الكود يجعل البوت يستجيب لأمر “$responding“. يأخذ هذا الأمر وسيطًا (argument) إما “true” أو “false“. إليك مثال على الاستخدام: “$responding true“. يقوم الكود أولاً بسحب الوسيط باستخدام value = msg.split("$responding ",1)[1] (كما كان من قبل، لاحظ المسافة في “$responding “). ثم توجد جملة if/else تقوم بتعيين مفتاح “responding” في قاعدة البيانات بشكل مناسب وترسل رسالة إشعار إلى ديسكورد. إذا كان الوسيط أي شيء آخر غير “true“، يفترض الكود أنه “false“. اكتمل كود البوت! يمكنك الآن تشغيل البوت وتجربته. ولكن هناك خطوة أخرى مهمة سنناقشها بعد ذلك.

إعداد البوت للعمل بشكل مستمر

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

الطريقة الأولى: استخدام خطة Always On المدفوعة في Repl.it

الطريقة الأولى والأبسط هي الاشتراك في خطة مدفوعة في Repl.it. تسمى أرخص خطة مدفوعة لديهم “Hacker Plan” وتتضمن خمسة repls تعمل دائمًا (always-on). يمكنك الحصول على ثلاثة أشهر مجانية باستخدام هذا الرابط (محدود لأول 1000 شخص): https://repl.it/claim?code=tryalwayson2103

بمجرد الاشتراك في تلك الخطة، افتح Repl الخاص بك وانقر على الاسم في الأعلى. ثم حدد خيار “Always On“.

صورة توضح تفعيل خيار "Always On" في Repl.it.

الطريقة الثانية: الاستضافة المجانية المستمرة باستخدام Uptime Robot

هناك طريقة أخرى لإبقاء الكود الخاص بك يعمل حتى على الطبقة المجانية، ولكنها أكثر تعقيدًا بعض الشيء. سيستمر Repl.it في تشغيل خادم ويب (web server) حتى بعد إغلاق علامة التبويب. ولكن حتى خادم الويب سيعمل لمدة تصل إلى ساعة واحدة فقط دون أي استخدام. إليك ما تقوله وثائق repl.it:

Once deployed, the server will continue to run in the background, even after you close the browser tab. The server will stay awake and active until an hour after its last request, after which it will enter a sleeping stage. Sleeping repls will be woken up as soon as it receives another request; there is no need to re-run the repl. However, if you make changes to your server, you will need to restart the repl in order to see those changes reflected in the live version.

لإبقاء البوت يعمل بشكل مستمر، سنستخدم خدمة مجانية أخرى تسمى Uptime Robot على https://uptimerobot.com/. يمكن إعداد Uptime Robot لإرسال طلبات ping إلى خادم الويب الخاص بالبوت على repl.it كل 5 دقائق. مع طلبات ping المستمرة، لن يدخل البوت أبدًا في مرحلة السكون وسيستمر في العمل. لذلك علينا القيام بشيئين آخرين لجعل البوت الخاص بنا يعمل بشكل مستمر: إنشاء خادم ويب في repl.it وإعداد Uptime Robot لإرسال ping باستمرار إلى خادم الويب.

إنشاء خادم ويب في Repl.it

إنشاء خادم ويب أبسط مما تتخيل. للقيام بذلك، أنشئ ملفًا جديدًا في مشروعك يسمى keep_alive.py. ثم أضف الكود التالي:

from flask import Flask
from threading import Thread

app = Flask('')

@app.route('/')
def home():
    return "Hello. I am alive!"

def run():
    app.run(host='0.0.0.0',port=8080)

def keep_alive():
    t = Thread(target=run)
    t.start()

في هذا الكود، نستخدم Flask لبدء خادم ويب. يعيد الخادم “Hello. I am alive.” لأي شخص يزوره. سيعمل الخادم على خيط منفصل (separate thread) عن البوت الخاص بنا. لن نناقش كل شيء هنا لأن البقية ليست ذات صلة ببوتنا حقًا. الآن نحتاج فقط إلى أن يقوم البوت بتشغيل خادم الويب هذا. أضف السطر التالي نحو الجزء العلوي من main.py لاستيراد الخادم.

from keep_alive import keep_alive

لبدء خادم الويب عند تشغيل main.py، أضف السطر التالي كسطر ما قبل الأخير، قبل تشغيل البوت مباشرةً. keep_alive()

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

صورة توضح رابط URL لخادم الويب الذي تم إنشاؤه في Repl.it.

إعداد خدمة Uptime Robot

الآن نحتاج إلى إعداد Uptime Robot لإرسال ping إلى خادم الويب كل خمس دقائق. سيؤدي هذا إلى تشغيل البوت بشكل مستمر. أنشئ حسابًا مجانيًا على https://uptimerobot.com/. بمجرد تسجيل الدخول إلى حسابك، انقر على “Add New Monitor“.

صورة توضح زر "Add New Monitor" في Uptime Robot.

بالنسبة للمراقب الجديد، حدد “HTTP(s)” كنوع المراقب (Monitor Type) وسمه ما شئت. ثم، الصق رابط URL الخاص بخادم الويب الخاص بك من repl.it. أخيرًا، انقر على “Create Monitor“.

صورة توضح إعداد مراقب جديد في Uptime Robot باستخدام رابط URL لخادم الويب.لقد انتهينا! الآن سيعمل البوت بشكل مستمر حتى يتمكن الأشخاص دائمًا من التفاعل معه على Repl.it.

الخلاصة

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

الخلاصة التقنية

يمثل هذا الدليل خطوة ممتازة للمطورين الطموحين والمهتمين بأتمتة المهام والتفاعل في منصة ديسكورد. من خلال الاستفادة من قوة بايثون ومكتبة discord.py سهلة الاستخدام، بالإضافة إلى بيئة Repl.it السحابية المجانية، يمكن للمستخدمين بناء بوتات وظيفية دون عوائق التثبيت أو تكاليف الاستضافة. استخدام قاعدة بيانات Repl.it المدمجة لتمكين تفاعل المستخدمين وإضافة المحتوى يضيف طبقة قيمة من الديناميكية، بينما تضمن خدمة Uptime Robot استمرارية عمل البوت على مدار الساعة، مما يجعل هذا الحل مثاليًا للمشاريع الشخصية والتعليمية. إن هذا النهج يفتح آفاقًا واسعة للإبداع في تطوير بوتات ديسكورد.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *