إنشاء وشم مخصص بصورة من خلال واجهة برمجة التطبيقات

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

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

يجب أن يكون هذا سهل القراءة حتى لو لم تكن مبرمج بايثون. يمكنك حتى تكراره باستخدام curl على سطر الأوامر، إذا أردت.

هذا يتوقع أن يكون مفتاح واجهة برمجة التطبيقات الخاص بك في متغير بيئة DISCOURSE_API_KEY.

#!/usr/bin/python3

import os         # لقراءة البيئة
import sys        # للخروج. :)
import hashlib    # لتجزئة الصورة

import requests   # يقوم بكل العمل الحقيقي


# معلومات الموقع والمصادقة
DISCOURSE = "discussion.fedoraproject.org"
DISCOURSE_API_USER = "mattdm"
DISCOURSE_API_KEY = os.getenv("DISCOURSE_API_KEY")
if not DISCOURSE_API_KEY:
    print(f"خطأ: يجب تعيين DISCOURSE_API_KEY في البيئة", file=sys.stderr)
    sys.exit(2)

# معلومات لشارتك. من المفترض، في الاستخدام الحقيقي لن تقوم بتشفير هذا بشكل ثابت.
NAME = "Apex"
IMAGE = "apex.png"
DESCRIPTION = "Blessing of the FPL"
MORE = "You are awesome and everyone should know!"
TARGET_USER = "mattdm"

# رؤوس المصادقة الخاصة بنا، من الأعلى.
HEADERS = {'Api-Key': DISCOURSE_API_KEY, 'Api-Username': DISCOURSE_API_USER}

# من هذا، يمكنك الحصول على معرفات وأوصاف مجموعات الشارات،
# وأنواع الشارات المختلفة. إذا أردت. لا تستخدم هذا في هذا المثال.
r = requests.get(f"https://{DISCOURSE}/admin/badges.json", headers=HEADERS)
if r.status_code != 200:
    print(f"خطأ في الحصول على قائمة الشارات: تم الحصول على {r.status_code}", file=sys.stderr)
    sys.exit(1)

# تحقق من أن الاسم غير موجود بالفعل.
# ربما هناك طريقة أفضل للقيام بذلك، ولكن هذا يكفي.
if NAME in list(map(lambda x: x['name'], r.json()['badges'])):
    print(f"خطأ: الشارة '{NAME}' موجودة بالفعل.")
    sys.exit(3)

# قراءة الصورة. ستحتاج إلى معالجة أخطاء أفضل هنا في كود حقيقي!
with open(IMAGE, "rb") as f:
    image_data = f.read()

# ربما يجب إجراء بعض الفحوصات المنطقية على
# حجم ملف الصورة/الأبعاد في هذا المكان بالضبط....

# ولكن على أي حال، قم بتجميع حزمة معلومات عنها لتحميلها.
# الشيء الوحيد الصعب هنا حقًا هو الحصول على مجموع التحقق من الصورة.
file_info = {'file_name': f'{IMAGE}',
             'file_size': f'{len(image_data)}',
             'type': 'badge_image',
             'metadata[sha1-checksum]': hashlib.sha1(image_data).hexdigest(),
             }


# واطلب من Discourse أين ترسلها.
r = requests.post(
    f"https://{DISCOURSE}/uploads/generate-presigned-put", json=file_info, headers=HEADERS)
if r.status_code != 200:
    print(
        f"خطأ في طلب مكان تحميل الصورة: تم الحصول على {r.status_code}", file=sys.stderr)
    sys.exit(1)

upload_url = r.json()['url']
upload_uid = r.json()['unique_identifier']

# الآن ضعها حيث قيل لنا.
r = requests.put(upload_url, data=image_data)
if r.status_code != 200:
    print(
        f"خطأ في تحميل الصورة إلى التخزين الخارجي: تم الحصول على {r.status_code}", file=sys.stderr)
    sys.exit(1)

# وأخبر Discourse أن ذلك نجح، واحصل على معرف يمكننا الرجوع إليه لاحقًا.
r = requests.post(f"https://{DISCOURSE}/uploads/complete-external-upload",
                  data=f'unique_identifier={upload_uid}', headers=HEADERS)
if r.status_code != 200:
    print(f"خطأ في إكمال التحميل: تم الحصول على {r.status_code}", file=sys.stderr)
    sys.exit(1)
image_id = r.json()['id']


# ملاحظة: إذا كنت ترغب في استخدام Font Awesome، اترك `image_upload_id` فارغًا و
# بدلاً من ذلك قم بتعيين `icon` إلى اسم Font Awesome المقابل. وبالطبع
# يمكنك تخطي كل شيء تحميل الصورة في هذه الحالة!
badge = {'allow_title': 'true',
         'multiple_grant': 'false',
         'listable': 'true',
         'show_posts': 'false',
         'target_posts': 'false',
         'name': f'{NAME}',
         'description': f'{DESCRIPTION}',
         'long_description': f'{DESCRIPTION} {MORE}',
         'image_upload_id': f'{image_id}',
         'badge_grouping_id': '5',
         'badge_type_id': '1',
         }


r = requests.post(
    f"https://{DISCOURSE}/admin/badges.json", json=badge, headers=HEADERS)
if r.status_code != 200:
    print(f"خطأ في إنشاء الشارة: تم الحصول على {r.status_code}", file=sys.stderr)
    sys.exit(1)

badge_id = r.json()['badge']['id']

print(f'تم إنشاء الشارة "{NAME}: {DESCRIPTION}" بالمعرف {badge_id}!')


# وللإكمال، امنح الشارة!

# يمكنك أيضًا إضافة "سبب"، والذي يجب أن يرتبط بمنشور أو موضوع.
bestow = {'username': f"{TARGET_USER}", 'badge_id': f'{badge_id}'}

r = requests.post(f"https://{DISCOURSE}/user_badges",
                  json=bestow, headers=HEADERS)
if r.status_code != 200:
    print(f"خطأ في منح الشارة: تم الحصول على {r.status_code}", file=sys.stderr)
    sys.exit(1)

print(f'تم منح المستخدم {TARGET_USER} الشارة الجديدة!')

7 إعجابات

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

لم تعد بحاجة إلى مفتاح واجهة برمجة تطبيقات مسؤول عام لهذا الغرض - عند إنشاء مفتاح واجهة برمجة تطبيقات، يمكنك تحديد أشياء مختلفة تتعلق بإنشاء الشارات أو منحها أو إتلافها. لا تنسَ “التحميل” إذا كنت تريد القيام بما يوضحه هذا المثال وإضافة صورك الخاصة. هذا في قسم منفصل عن أذونات واجهة برمجة تطبيقات الشارات.

إعجابَين (2)

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

3 إعجابات