منتديات ريكسار
منتديات ريكسار تنبيه النظام

دليل برمجة إضافات ForumREXAR

إضافة ForumREXAR ملف XML واحد، بدون أي كود JavaScript أو Go. تعلن فيه ماذا تعرض وأين، والمنتدى يفحصه وينفذه بأمان.

هذا الدليل للمطورين ولوكلاء الذكاء الاصطناعي. والنسخة الخام منه للوكلاء: /static/docs/plugin-guide.md

ابدأ في خمس دقائق

  1. أنشئ ملفاً باسم hello_box.xml بترميز UTF-8.
  2. ضع فيه المثال التالي.
  3. من لوحة التحكم افتح admin?tab=plugins، ثم ارفع الملف.
  4. تُثبت الإضافة معطلة دائماً، فاضغط زر التفعيل.
  5. افتح الرئيسية وسترى الصندوق.
<?xml version="1.0" encoding="UTF-8"?>
<plugin schema_version="1.0">
    <id>hello_box</id>
    <name>صندوق الترحيب</name>
    <version>1.0.0</version>
    <min_rexar_version>1.0.0</min_rexar_version>
    <api_version>1</api_version>
    <author>اسمك</author>
    <description>يعرض رسالة ترحيب أعلى أقسام الرئيسية.</description>
    <icon>👋</icon>
    <hook>HOME_ABOVE_FORUMS</hook>
    <settings>
        <setting key="message" type="string" label="نص الترحيب" default="أهلاً بكم" max_len="100"/>
    </settings>
    <template><![CDATA[
<div class="vb-bottom-box">
    <div class="vb-box-header">ترحيب</div>
    <div class="vb-box-body">{{index .settings "message"}}</div>
</div>
]]></template>
</plugin>

عناصر ملف الإضافة

العنصرإلزاميالقاعدة
schema_version على pluginنعمالقيمة 1.0
idنعمأحرف إنجليزية صغيرة وأرقام و_، من 3 إلى 50 حرفاً
nameنعمحتى 100 حرف، بدون < أو >
versionنعممثل 1.0.0، والتحديث يجب أن يكون أحدث
min_rexar_versionنعمأقل إصدار تعمل عليه الإضافة، و1.0.0 هو الأدنى
api_versionنعمالقيمة 1
authorنعمحتى 80 حرفاً
descriptionنعمحتى 300 حرف
iconلارمز قصير حتى 16 حرفاً
hook مع templateعند الصندوقمكان الظهور وقالبه
data_sourceلامصدر بيانات أو أكثر مفصولة بفاصلة
settingsلاحتى 10 إعدادات
themeلامظهر يغيّر الألوان
actionsلاحتى 10 إجراءات للأعضاء
page_title مع page_templateعند الصفحةصفحة خاصة بالإضافة

يجب أن تحتوي الإضافة على واحد على الأقل من: صندوق، أو مظهر، أو صفحة. والحد الأقصى لحجم الملف 256KB.

المعرفات forum_stats وwho_is_online وlive_chat محجوزة.

ابدأ المعرف باسمك، مثل saleh_top_box، حتى لا يتكرر. وقبل النشر تأكد من عدم استخدامه في قسم الإضافات، فأول من ينشر معرفاً يملكه هناك.

أماكن الظهور

الاسمالمكانالسياق
HEADER_BELOWتحت الهيدر في صفحات المنتدىلا يوجد
PAGE_BOTTOMأسفل الصفحة فوق الشريط السفليلا يوجد
SIDEBAR_BOTTOMأسفل القائمة الجانبيةلا يوجد
HOME_ABOVE_FORUMSأعلى أقسام الرئيسيةلا يوجد
HOME_BELOW_FORUMSأسفل أقسام الرئيسيةلا يوجد
FORUM_TOPأعلى صفحة القسمقسم
FORUM_BOTTOMأسفل صفحة القسمقسم
TOPIC_TOPأعلى الموضوعموضوع
TOPIC_BOTTOMأسفل الموضوعموضوع
POST_AUTHOR_BELOWأسفل بطاقة كاتب كل مشاركةعضو
PROFILE_BOTTOMأسفل الملف الشخصيعضو

لا تظهر الإضافات في لوحة التحكم ولا في صفحة التثبيت. ولا يصل إلى النقاش الحي إلا SIDEBAR_BOTTOM. ويُسمح بخمس إضافات مفعلة في المكان الواحد.

القوالب

القالب هو Go html/template داخل <![CDATA[ ... ]]>، والمنتدى يهرّب القيم تلقائياً.

ما تقرؤهالصيغة
إعداد{{index .settings "key"}}
قائمة بيانات{{range .data.latest_topics}} ... {{end}}
حقل من صف{{index . "title"}}
إعداد من داخل range{{index $.settings "key"}}
إحصائية{{index .data.forum_stats "members_count"}}
سياق الصفحة{{index .context "username"}}
نتيجة تصويت{{index .storage.poll "yes"}}
سجلات الأعضاء{{range .storage.ideas}} ... {{end}}

الدوال المسموحة فقط: index وlen وeq وne وlt وle وgt وge وand وor وnot.

القيود:

  • {{if}} و{{range}} و{{with}} مسموحة، وrange على .data و.storage فقط، بعمق 2 كحد أقصى.
  • لا range داخل with.
  • لا متغيرات مثل {{$x := ...}}، ولا define أو template أو block.
  • لا نصوص ثابتة داخل القوسين مثل {{"نص"}}؛ النص يُكتب خارجهما، والنصوص داخلها لدوال المقارنة وindex فقط.
  • حجم ناتج الإضافة حتى 32KB، ووقت عرضها حتى 200ms.

الوسوم المسموحة

div span p strong b em i u br hr ul ol li table thead tbody tr th td a img h3 h4 button textarea input label

الخصائص

الخاصيةالقاعدة
classvb-bottom-box وvb-box-header وvb-box-body، أو أسماء تبدأ بـ st-plugin-
href على aيبدأ بـ /f.aspx أو https://
src على imgيبدأ بـ /static/ فقط
alt وwidth وheightعلى img
target_blank فقط
title وdir وalignمسموحة
colspan وrowspanعلى td وth

ممنوع: id وstyle وكل on... وأي data- غير أدوات التفاعل أدناه، وكذلك script وform وiframe وstyle كوسوم.

مصادر البيانات

البيانات عامة بمستوى الزائر: لا أقسام إدارية، ولا مواضيع مخفية، ولا بريد أو IP. وتتحدث كل 30 ثانية تقريباً، والصندوق يُحفظ حتى 60 ثانية. وعدد الصفوف يحدده إعداد باسم limit، وافتراضه 5 وأقصاه 20.

المصدرالحقول
top_postersrank id username role_color posts_count avatar_url profile_url
latest_topicsid title url author author_url forum_name forum_url replies_count views_count
newest_membersid username role_color avatar_url profile_url
forum_statstopics_count posts_count members_count online_members online_guests

forum_stats قيمة واحدة تُقرأ بـ index، والبقية قوائم تُقرأ بـ range.

<?xml version="1.0" encoding="UTF-8"?>
<plugin schema_version="1.0">
    <id>guide_latest_box</id>
    <name>أحدث المواضيع</name>
    <version>1.0.0</version>
    <min_rexar_version>1.0.0</min_rexar_version>
    <api_version>1</api_version>
    <author>اسمك</author>
    <description>يعرض أحدث المواضيع مع عدد الأعضاء.</description>
    <hook>HOME_BELOW_FORUMS</hook>
    <data_source>latest_topics,forum_stats</data_source>
    <settings>
        <setting key="limit" type="int" label="عدد المواضيع" default="5" min="1" max="20"/>
    </settings>
    <template><![CDATA[
<div class="vb-bottom-box">
    <div class="vb-box-header">أحدث المواضيع</div>
    <div class="vb-box-body">
        {{range .data.latest_topics}}<a href="{{index . "url"}}">{{index . "title"}}</a>{{end}}
        <p>الأعضاء: {{index .data.forum_stats "members_count"}}</p>
    </div>
</div>
]]></template>
</plugin>

سياق الصفحة

تقرأ الإضافة بيانات الصفحة الحالية من .context:

السياقالحقول
عضوid username role_color role_title avatar_url profile_url posts_count
موضوعid title url author author_url forum_name forum_url replies_count views_count
قسمid name description url topics_count posts_count
<?xml version="1.0" encoding="UTF-8"?>
<plugin schema_version="1.0">
    <id>guide_author_badge</id>
    <name>شارة كبار المشاركين</name>
    <version>1.0.0</version>
    <min_rexar_version>1.0.0</min_rexar_version>
    <api_version>1</api_version>
    <author>اسمك</author>
    <description>شارة تحت الكاتب إذا تجاوز عدداً من المشاركات.</description>
    <hook>POST_AUTHOR_BELOW</hook>
    <settings>
        <setting key="min_posts" type="int" label="الحد الأدنى" default="100" min="1" max="100000"/>
    </settings>
    <template><![CDATA[
{{if ge (index .context "posts_count") (index .settings "min_posts")}}
<div class="vb-bottom-box"><div class="vb-box-header">عضو مميز</div></div>
{{end}}
]]></template>
</plugin>

الإعدادات

تظهر الإعدادات للمدير في لوحة التحكم، وتُفحص قيمها عند الحفظ.

النوعالخصائص
stringmax_len حتى 250، وبدون < أو > في القيمة
intmin وmax إلزاميان
booldefault يكون true أو false
colorلون بصيغة #1a2b3c، ويظهر كمنتقي ألوان
selectعناصر <option value="..." label="..."/> داخل الإعداد

كل إعداد يحتاج key وtype وlabel وdefault. والمفتاح أحرف صغيرة وأرقام و_، من 2 إلى 30 حرفاً.

المظاهر

عنصر <theme> يحمل CSS يغيّر الألوان والخطوط، ويمكن استخدام إعدادات اللون فيه بصيغة var(--setting-key).

الخصائص المسموحة: color وbackground وbackground-color وbackground-image وborder وأنواعه وborder-radius وoutline-color وbox-shadow وtext-shadow وtext-decoration-color وfont-family وfont-weight وfont-style وcaret-color وaccent-color، إضافة إلى متغيرات CSS مثل --startimes-blue.

الدوال المسموحة: rgb وrgba وhsl وhsla وlinear-gradient وradial-gradient وvar.

الممنوع: url() و@import وأي قاعدة @، وposition وdisplay وopacity وwidth وخصائص التخطيط، و::before و::after ومحددات الخصائص [...].

المحولات المسموحة: :hover و:focus و:active و:visited و:root و:first-child و:last-child.

يعمل مظهر واحد فقط في كل مرة، ولا يُطبق على لوحة التحكم. وللمدير زر معاينة قبل التفعيل.

<?xml version="1.0" encoding="UTF-8"?>
<plugin schema_version="1.0">
    <id>guide_green_theme</id>
    <name>المظهر الأخضر</name>
    <version>1.0.0</version>
    <min_rexar_version>1.0.0</min_rexar_version>
    <api_version>1</api_version>
    <author>اسمك</author>
    <description>يغيّر ترويسات المنتدى إلى الأخضر.</description>
    <settings>
        <setting key="primary" type="color" label="اللون الأساسي" default="#047857"/>
    </settings>
    <theme><![CDATA[
:root { --startimes-blue: var(--setting-primary); }
.table-columns-header, .table-columns-header th, .vb-box-header {
    background: var(--setting-primary) !important;
}
]]></theme>
</plugin>

التفاعل

المطور يعلن الإجراءات، والمنتدى ينفذها. وكل إجراء يتطلب عضواً مسجلاً.

الخاصيةvote تصويتentry نص
idإلزاميإلزامي
optionsإلزامي، حتى 20 خياراًغير مسموح
max_lenغير مسموحافتراضي 200، وأقصى 500
max_entriesغير مسموحافتراضي 100، وأقصى 500
cooldownثوانٍ، افتراضي 30، وأقل قيمة 3كذلك

الخيار total محجوز لمجموع الأصوات. وعند تجاوز max_entries يُحذف أقدم سجل. والبيانات في ملف مستقل حتى 2MB، وتبقى عند تحديث الإضافة، وتُحذف بحذفها. وللمدير زر مسح البيانات.

أدوات الواجهة

الخاصيةالوسمالوظيفة
data-plugin-actionbuttonاسم الإجراء
data-plugin-valuebuttonخيار التصويت
data-plugin-fieldbuttonاسم الحقل المرتبط بالزر
data-plugin-inputinput وtextareaاسم الحقل
data-plugin-statusdiv وspan وpمكان رسالة النجاح أو الخطأ
data-plugin-openbuttonيفتح نافذة
data-plugin-closebuttonيغلق النافذة
data-plugin-modaldivجسم النافذة، وعنصره الأول هو محتواها

قيم هذه الخصائص أحرف إنجليزية وأرقام و_ و- حتى 40 حرفاً. وinput نوعه text فقط، وbutton لا يرسل نموذجاً. وخصائص الحقول المسموحة placeholder وmaxlength وrows.

الصفحة الخاصة

رابطها /f.aspx?plugin=ID. وتعرف الصفحة الزائر عبر .viewer.logged_in و.viewer.username، وصوته عبر {{index .viewer.votes "poll"}}. أما الصناديق فمشتركة بين الزوار، فلا تعرف الزائر الحالي.

<?xml version="1.0" encoding="UTF-8"?>
<plugin schema_version="1.0">
    <id>guide_poll_page</id>
    <name>استفتاء واقتراحات</name>
    <version>1.0.0</version>
    <min_rexar_version>1.0.0</min_rexar_version>
    <api_version>1</api_version>
    <author>اسمك</author>
    <description>استفتاء في الرئيسية وصفحة لاقتراحات الأعضاء.</description>
    <hook>HOME_ABOVE_FORUMS</hook>
    <actions>
        <action id="poll" type="vote" options="yes,no" cooldown="5"/>
        <action id="ideas" type="entry" max_len="300" max_entries="200" cooldown="30"/>
    </actions>
    <template><![CDATA[
<div class="vb-bottom-box">
    <div class="vb-box-header">هل يعجبك المنتدى؟</div>
    <div class="vb-box-body">
        <button data-plugin-action="poll" data-plugin-value="yes">نعم ({{index .storage.poll "yes"}})</button>
        <button data-plugin-action="poll" data-plugin-value="no">لا ({{index .storage.poll "no"}})</button>
        <button data-plugin-open="about">التفاصيل</button>
        <a href="/f.aspx?plugin=guide_poll_page">الاقتراحات</a>
        <span data-plugin-status="box"></span>
        <div data-plugin-modal="about">
            <div>
                <p>صوتك يُحتسب مرة واحدة ويمكنك تغييره.</p>
                <button data-plugin-close="about">إغلاق</button>
            </div>
        </div>
    </div>
</div>
]]></template>
    <page_title>اقتراحات الأعضاء</page_title>
    <page_template><![CDATA[
<div class="vb-bottom-box">
    <div class="vb-box-header">اقتراحات الأعضاء</div>
    <div class="vb-box-body">
        {{if .viewer.logged_in}}
        <textarea data-plugin-input="ideas" maxlength="300" rows="3" placeholder="اكتب اقتراحك"></textarea>
        <button data-plugin-action="ideas" data-plugin-field="ideas">إرسال</button>
        <span data-plugin-status="page"></span>
        {{end}}
        {{range .storage.ideas}}
        <p><a href="{{index . "profile_url"}}">{{index . "username"}}</a>: {{index . "text"}}</p>
        {{end}}
    </div>
</div>
]]></page_template>
</plugin>

حقول سجلات .storage: id وusername وprofile_url وtext وtime، وتُعرض آخر 50 سجلاً.

التحديث

ارفع ملفاً بنفس id ورقم version أعلى، مع تحديد خيار "تحديث إضافة مثبتة". تعود الإضافة معطلة للمراجعة، وتبقى إعداداتها وبياناتها.

عند فشل العرض 5 مرات متتالية تتعطل الإضافة تلقائياً، ويظهر السبب في لوحة التحكم. وخيار REXAR_SAFE_MODE=1 في بيئة التشغيل يوقف كل الإضافات.

رسائل الرفض الشائعة

الرسالةالسبب والحل
forbidden HTML tagوسم غير مسموح، راجع قائمة الوسوم
disallowed CSS classاستخدم st-plugin- قبل اسم الكلاس
attribute "style" is forbiddenلا style داخل القالب، استخدم <theme>
forbidden template functionدالة غير مسموحة، راجع قائمة الدوال
direct string literalانقل النص خارج {{ }}
custom template variablesاحذف المتغيرات واستخدم index
a href must start withالرابط يبدأ بـ /f.aspx أو https://
img src must start with /static/الصور من ملفات الموقع فقط
unsupported or unknown <hook>اسم مكان غير صحيح، راجع الجدول
property ... is not allowed in <theme>خاصية CSS غير مسموحة
requires ForumREXAR versionالمنتدى أقدم من min_rexar_version
يجب أن يكون أحدثارفع رقم version قبل التحديث

تعليمات لوكلاء الذكاء الاصطناعي

عند إنشاء إضافة التزم بما يلي:

  1. أخرج ملف XML واحداً كاملاً بترميز UTF-8، ولا تكتب JavaScript أو CSS خارج <theme>.
  2. استخدم فقط العناصر والأسماء الواردة هنا، ولا تخمن أسماء بيانات أو أماكن غير مذكورة.
  3. ضع القوالب والمظاهر داخل <![CDATA[ ... ]]>.
  4. اجعل id فريداً بأحرف صغيرة، وابدأ الإصدار من 1.0.0.
  5. للتنسيق استخدم vb-bottom-box وvb-box-header وvb-box-body لتطابق شكل المنتدى.
  6. إذا طلب المستخدم شيئاً غير مدعوم، فأخبره بالقيد بدل محاولة الالتفاف عليه.
  7. بعد الرفع اقرأ رسالة الرفض، وأصلح السبب نفسه فقط، ثم أعد المحاولة.