بالتأكيد، الشارات المضمنة … لطيفة. لا يوجد شيء خاطئ بها على الإطلاق. ولكن، ماذا لو أردت المزيد؟ ماذا لو أردت تجاوز مجموعة الرموز المعرفة مسبقًا؟ بالتأكيد، هناك صفحة مسؤول حيث يمكنك تحميلها. ولكن ماذا لو أردت إنشاء الكثير من الشارات؟
حسنًا، أخبار سارة! يمكنك القيام بذلك من خلال واجهة برمجة التطبيقات. إليك كود بايثون يوضح كيفية عمل ذلك. (وهو يمنح الشارة في النهاية، لمزيد من الدقة.)
يجب أن يكون هذا سهل القراءة حتى لو لم تكن مبرمج بايثون. يمكنك حتى تكراره باستخدام 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} الشارة الجديدة!')