برمجة JavaScript

يدعم Chute برمجة JavaScript لتعديل الطلبات/الاستجابات المتقدم، مطابقة القواعد المخصصة، تحليل DNS، والمهام المجدولة. تستخدم السكريبتات محرك Apple JavaScriptCore وتتبع واجهة برمجة السكريبتات المتوافقة مع Surge.

تعرف السكريبتات في القسم [Script] من ملف الإعدادات.

الإعدادات

[Script]
MyScript = type=http-request, script-path=/path/to/script.js, pattern=^https?://example\.com, requires-body=true, max-size=262144, timeout=10, argument=myArg
CronJob = type=cron, script-path=/path/to/cron.js, cron-expression=*/30 * * * *

معاملات السكريبت

المعامل مطلوب الافتراضي الوصف
type نعم http-request نوع تشغيل السكريبت (انظر أدناه)
script-path نعم مسار ملف محلي أو رابط HTTP(S) لسكريبت JS
pattern لا (مطابقة الكل) نمط رابط بتعبير نمطي لتصفية وقت تشغيل السكريبت
requires-body لا اكتشاف تلقائي فرض استلام السكريبت لمحتوى الطلب/الاستجابة الكامل
max-size لا 131072 (128KB) الحد الأقصى لحجم المحتوى بالبايت للسكريبتات التي تصل للمحتوى. إذا تجاوز المحتوى المجمّع هذا الحجم، يُتخطى السكريبت لذلك الطلب (لا يتم اقتطاع المحتوى)
timeout لا 5.0 ثانية مهلة تنفيذ لكل سكريبت. القيم فوق 30 ثانية تُخفض إلى 30
argument لا نص وسيط مخصص متاح كـ $argument في JS
debug لا false محجوز؛ لا تأثير له حالياً
cron-expression لا تعبير جدولة cron (لنوع cron فقط)
wake-system لا false محجوز؛ يُحلَّل لكن لا تأثير له حالياً
enable لا true تفعيل أو تعطيل هذا السكريبت
script-update-interval لا 0 استطلاع تحديث السكريبتات البعيدة (انظر نموذج التنفيذ)

أنواع السكريبتات

النص النوعي التعداد الوصف
http-request HTTP Request اعتراض وتعديل طلبات HTTP قبل التوجيه
http-response HTTP Response اعتراض وتعديل استجابات HTTP قبل العميل
http-request-before-send HTTP Request Before Send تعديل الطلب بعد جمع المحتوى الكامل، قبل الإرسال
rule Rule منطق مطابقة قواعد مخصص
dns DNS تحليل DNS مخصص
cron Cron سكريبتات مجدولة/موقوتة
event Event معالجات أحداث النظام (مثال: network-changed)

اكتشاف المحتوى التلقائي: إذا كان مصدر السكريبت يحتوي على $request.body أو $response.body، سيتم توفير المحتوى تلقائياً حتى max-size. استخدم requires-body=true لفرض هذا السلوك.


مرجع JavaScript API

تعمل السكريبتات في بيئة JavaScriptCore معزولة مع توفر الكائنات العامة التالية.

$request (للقراءة فقط)

متوفر في: http-request, http-response, http-request-before-send, rule

الخاصية النوع الوصف
.url String رابط الطلب الكامل
.method String طريقة HTTP (GET, POST, إلخ) أو QUERY لـ DNS
.headers Object ترويسات الطلب كأزواج key-value
.body String or null محتوى الطلب (مفكوك UTF-8)
.hostname String اسم المضيف الهدف
.destPort Number منفذ الوجهة
.processPath String مسار العملية الطالبة (macOS فقط)
.userAgent String قيمة ترويسة User-Agent
.sourceIP String عنوان IP المصدر
.listenPort Number منفذ استماع البروكسي
.requestId String معرف طلب فريد
.dnsResult String عنوان IP المحلل
.srcPort Number منفذ المصدر
.protocol String البروتوكول المكتشف: http, https, tcp, dns

$response (للقراءة فقط)

متوفر في: http-response

الخاصية النوع الوصف
.status Number رمز حالة HTTP
.headers Object ترويسات الاستجابة كأزواج key-value
.body String or null محتوى الاستجابة (مفكوك UTF-8)

$done(value) — معالج الإكمال

يجب استدعاؤه مرة واحدة بالضبط في نهاية السكريبت للإشارة إلى الاكتمال. يتوقف تنفيذ السكريبت حتى يتم استدعاء $done() أو انتهاء المهلة.

$done({})                        // تمرير — لا تعديلات
$done()                          // إجهاض الاتصال
$done({matched: true})           // نتيجة مطابقة القاعدة (لسكريبتات القواعد فقط)
$done({address: "1.2.3.4"})      // نتيجة DNS (لسكريبتات DNS فقط)

قيم إرجاع سكريبت طلب HTTP:

$done({
    url: "https://new.example.com/path",     // إعادة كتابة الرابط
    headers: {"X-Custom": "value"},           // تعديل الترويسات
    body: "new request body",                 // تعديل المحتوى
    response: {                               // إرجاع استجابة اصطناعية (تخطي الخادم العلوي)
        status: 200,
        headers: {"Content-Type": "text/html"},
        body: "<html>Blocked</html>"
    }
})

عند توفير response، يتم اختصار الطلب: يرجع Chute الاستجابة الاصطناعية مباشرة إلى العميل دون الاتصال بالخادم العلوي. هذا مفيد للحظر، محاكاة APIs، أو إرجاع محتوى مخزن مؤقتاً.

قيم إرجاع سكريبت استجابة HTTP:

$done({
    status: 200,                              // تعديل رمز الحالة
    headers: {"X-Custom": "value"},           // تعديل ترويسات الاستجابة
    body: "new response body",                // تعديل محتوى الاستجابة
    url: "https://other.example.com"          // تشغيل إعادة توجيه 302
})

عند توفير url، يرجع Chute إعادة توجيه 302 إلى الرابط المعطى بدلاً من الاستجابة الأصلية. يجب إرجاع url مع واحد على الأقل من status / headers / body؛ النتيجة التي تحتوي على url فقط تُعامل كتمرير.

قيم إرجاع سكريبت DNS:

$done({address: "1.2.3.4"})                  // IP واحد
$done({addresses: ["1.2.3.4", "5.6.7.8"]})   // عدة IPs
$done({address: "10.0.0.1", ttl: 300})       // مع TTL مخصص (بالثواني، الافتراضي 60)

المفتاحان server / servers مقبولان لكن يتم تجاهلهما حالياً؛ يسقط التحليل إلى DNS العادي.

$httpClient — عميل HTTP غير متزامن

إجراء طلبات HTTP من داخل السكريبتات. يتم إلغاء جميع الطلبات عند $done() أو المهلة.

$httpClient.get(url, function(error, response, data) {
    if (error) {
        console.log("Request failed: " + error)
    } else {
        console.log("Status: " + response.status)
        console.log("Response: " + data)
    }
})

$httpClient.post(url, {headers: {...}, body: "...", timeout: 5}, callback)
$httpClient.put(url, options, callback)
$httpClient.del(url, options, callback)
$httpClient.head(url, options, callback)
$httpClient.options(url, options, callback)
$httpClient.patch(url, options, callback)

توقيع callback: callback(error, response, data)

  • error: نص الخطأ أو null
  • response: {status: Number, headers: Object} أو null
  • data: محتوى استجابة UTF-8 نصي أو null

$persistentStore — تخزين Key-Value

تخزين key-value دائم يبقى عبر إعادة تشغيل السكريبتات والعمليات. مدعوم بـ NSUserDefaults.

$persistentStore.write(data, key)   // تخزين قيمة
$persistentStore.read(key)          // استرجاع قيمة
$persistentStore.remove(key)        // إزالة قيمة

$notification — الإشعارات المحلية

نشر إشعارات نظام محلية.

$notification.post("Title", "Subtitle", "Notification body text")

$network — معلومات الشبكة

معلومات حالة الشبكة للقراءة فقط.

$network.dns   // مصفوفة من عناوين IP لخوادم DNS
$network.wifi  // {ssid: "WiFiName", bssid: null}

bssid دائماً null؛ ولا تُعبأ ssid إلا على iOS.

تنبيه: في الإصدارات الحالية، الخاصيتان $network و $environment غير مرئيتين للسكريبتات بسبب قيد في الجسر (bridging) وتُقرآن كـ undefined. بيانات $script الوصفية متاحة في سكريبتات cron و event فقط.

$environment — معلومات وقت التشغيل

$environment.system     // "iOS" أو "macOS"
$environment.appVersion // نص إصدار KLNEKit SDK

$utils — أدوات مساعدة

$utils.geoip("1.2.3.4")   // رمز الدولة (مثال: "US")
$utils.ipasn("1.2.3.4")   // رقم ASN (مثال: "13335")
$utils.ungzip(data)       // فك ضغط بيانات gzip

$klne — واجهة التحكم بالبروكسي

التحكم في وقت تشغيل البروكسي من السكريبتات.

$klne.getPolicyGroups()               // الحصول على جميع مجموعات السياسات
$klne.selectPolicy("Group", "Proxy")  // تبديل سياسة لمجموعة
$klne.getActiveConnections()          // سرد الاتصالات النشطة
$klne.closeConnection("id")           // إغلاق اتصال
$klne.flushDNS()                      // مسح ذاكرة DNS المؤقتة
$klne.startURLTest("Group")           // تشغيل اختبار رابط لمجموعة
$klne.reloadConfiguration()           // إعادة تحميل جميع الإعدادات
$klne.setOutboundMode("rule")         // تعيين النمط: "global", "proxy", "direct", "rule"
$klne.setHTTPCaptureEnabled(true)     // تفعيل/تعطيل MITM

$script — بيانات السكريبت الوصفية

$script.name       // اسم السكريبت من الإعدادات
$script.type       // نص نوع السكريبت
$script.startTime  // طابع زمني رتيب (ثوانٍ منذ مرجع إقلاع النظام، وليس Epoch)

globals لكل تنفيذ

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

$argument — وسيط السكريبت

القيمة النصية من معامل argument= في إعدادات السكريبت. متوفر في: http-request, http-response, http-request-before-send, rule, dns, cron.

console.log("Argument: " + $argument)

$domain — نطاق DNS (لسكريبتات DNS فقط)

اسم النطاق الذي يتم الاستعلام عنه. متوفر فقط في سكريبتات dns.

var domain = $domain  // مثال: "example.com"

$cronexp — تعبير Cron (لسكريبتات Cron فقط)

تعبير جدولة cron من إعدادات السكريبت. متوفر فقط في سكريبتات cron.

console.log("Schedule: " + $cronexp)  // مثال: "*/30 * * * *"

$event — معلومات الحدث (لسكريبتات Event فقط)

معلومات عن الحدث المشغل. حالياً فقط network-changed مدعوم.

console.log("Event: " + $event.name)  // "network-changed"

console — التسجيل

console.log("Debug message")    // سجل تفصيلي
console.warn("Warning message")  // سجل تحذيري
console.error("Error message")   // سجل تحذيري موسوم كخطأ JavaScript

setTimeout(fn, seconds) — مؤقت

جدولة دالة للتشغيل بعد تأخير.

setTimeout(function() {
    console.log("Delayed execution")
}, 2.5)  // 2.5 ثانية

$scriptImport(subScriptPath) — محمل السكريبتات الفرعية

تحميل وتقييم ملف JavaScript آخر. تُدعم مسارات الملفات المحلية فقط؛ روابط http(s):// و file:// مرفوضة. ($script محجوز لكائن بيانات السكريبت الوصفية.)

$scriptImport("/path/to/helper.js")

// تمرير البيانات بين السكريبتات باستخدام $persistentStore

تفاصيل أنواع السكريبتات

سكريبت طلب HTTP

ينفذ عند استلام ترويسات الطلب. يمكنه تعديل الرابط، الترويسات، والمحتوى قبل توجيه الطلب.

[Script]
ModifyHeaders = type=http-request, script-path=modify.js, pattern=^https://api\.example\.com

سكريبت استجابة HTTP

ينفذ عند استلام ترويسات الاستجابة. يمكنه تعديل الحالة، الترويسات، والمحتوى قبل الإرجاع إلى العميل.

[Script]
ModifyResponse = type=http-response, script-path=response.js, pattern=^https://api\.example\.com

سكريبت HTTP Request Before Send

ينفذ بعد جمع محتوى الطلب الكامل، قبل الإرسال إلى الخادم العلوي مباشرة. مفيد لتعديل محتويات طلبات POST/PUT.

[Script]
BeforeSend = type=http-request-before-send, script-path=before-send.js, pattern=^https://api\.example\.com, requires-body=true

سكريبت القاعدة

مطابقة قواعد مخصصة. يجب على السكريبت استدعاء $done({matched: true}) أو $done({matched: false}).

[Rule]
SCRIPT,MyRuleScript,DIRECT

[Script]
MyRuleScript = type=rule, script-path=rule.js

سكريبت DNS

تحليل DNS مخصص. يستقبل $domain ويرجع عنواناً (عناوين) محللة.

// dns.js
var domain = $domain
if (domain === "internal.example.com") {
    $done({address: "10.0.0.1", ttl: 300})
} else {
    $done({})  // تمرير إلى تحليل DNS العادي
}

سكريبت Cron

تنفيذ مجدول باستخدام تعبيرات cron. الحد الأدنى للفاصل هو 60 ثانية.

[Script]
HalfHourlyTask = type=cron, script-path=task.js, cron-expression=*/30 * * * *

يُحترم فقط حقل الدقائق من التعبير: */N يعمل كل N دقيقة. أي تعبير آخر ينطلق كل 60 ثانية، ويجب على السكريبت التحقق من الوقت الحالي بنفسه ليقرر ما إذا كان سيتصرف.

سكريبت الحدث

يتم تشغيله بواسطة أحداث النظام. حالياً يدعم حدث network-changed (ينطلق عند تغير شبكة WiFi أو الجوال).

[Script]
NetChange = type=event, script-path=network-changed.js

كائن $event متاح:

$event.name  // "network-changed"

أمثلة عملية

Redirect Mobile Devices

سكريبت http-request يعيد توجيه مستخدمي الجوال بناءً على User-Agent:

[Script]
MobileRedirect = type=http-request, script-path=mobile-redirect.js, pattern=^https://example\.com
// mobile-redirect.js
var ua = $request.headers["User-Agent"] || ""
if (/Mobile|Android|iPhone/.test(ua)) {
    $done({
        response: {
            status: 302,
            headers: {"Location": "https://m.example.com" + $request.url.replace(/.*example\.com/, "")},
            body: ""
        }
    })
} else {
    $done({})
}

Block Content in API Responses

سكريبت http-response يزيل الإعلانات والمحتوى المدعوم من استجابة JSON API:

[Script]
RemoveAds = type=http-response, script-path=remove-ads.js, pattern=^https://api\.example\.com/feed, requires-body=true
// remove-ads.js
var body = JSON.parse($response.body)
if (body.ads) {
    delete body.ads
}
if (body.recommendations) {
    body.recommendations = body.recommendations.filter(function(r) {
        return !r.sponsored
    })
}
$done({body: JSON.stringify(body)})

Modify Request Body Before Sending

سكريبت http-request-before-send ينقي حمولة POST:

[Script]
SanitizePayload = type=http-request-before-send, script-path=sanitize.js, pattern=^https://api\.example\.com/submit, requires-body=true
// sanitize.js
var body = JSON.parse($request.body)
body.clientSecret = "[REDACTED]"
body.timestamp = Math.floor(Date.now() / 1000)
$done({body: JSON.stringify(body)})

Custom Rule: Time-Based Routing

سكريبت rule يختار بروكسي مختلف حسب وقت اليوم:

[Rule]
SCRIPT,TimeBasedRule,ProxyA

[Script]
TimeBasedRule = type=rule, script-path=time-rule.js
// time-rule.js
var hour = new Date().getHours()
if (hour >= 9 && hour < 18) {
    $done({matched: false})  // السقوط إلى القاعدة التالية خلال ساعات العمل
} else {
    $done({matched: true})   // استخدام ProxyA خارج ساعات العمل
}

Custom DNS for Internal Domains

سكريبت dns يحل أسماء المضيفين الداخلية إلى عناوين IP محلية:

[Script]
InternalDNS = type=dns, script-path=internal-dns.js
// internal-dns.js
var internalHosts = {
    "gitlab.local": "10.0.0.10",
    "registry.local": "10.0.0.11",
    "monitor.local": "10.0.0.12"
}
if (internalHosts[$domain]) {
    $done({address: internalHosts[$domain], ttl: 3600})
} else {
    $done({})  // تمرير إلى DNS العادي
}

Auto-Switch Policy on Network Change

سكريبت event يبدل إلى مجموعة سياسات محافظة عند استخدام الجوال:

[Script]
NetSwitch = type=event, script-path=network-switch.js
// network-switch.js
if (!$network.wifi.ssid) {
    // على الجوال — استخدام مجموعة بيانات منخفضة
    $klne.selectPolicy("MainGroup", "LowDataProxy")
    console.log("Switched to cellular profile")
} else if ($network.wifi.ssid === "Office") {
    $klne.selectPolicy("MainGroup", "DIRECT")
    console.log("Switched to office profile")
}

Periodic Health Check

سكريبت cron يتحقق من صحة البروكسي كل 30 دقيقة:

[Script]
HealthCheck = type=cron, script-path=health-check.js, cron-expression=*/30 * * * *
// health-check.js
$httpClient.head("https://www.google.com/generate_204", {timeout: 10},
    function(error, response, data) {
        if (error || response.status !== 204) {
            console.error("Health check failed: " + (error || "status " + response.status))
            $notification.post("Chute Alert", "Health Check", "Cannot reach Google")
        } else {
            console.log("Health check OK")
        }
        $done({})
    }
)

استدعِ $done({}) داخل الـ callback — إكمال السكريبت يلغي جميع طلبات $httpClient المعلقة، لذا فإن $done() متزامناً في نهاية السكريبت سيلغي فحص الصحة قبل وصول استجابته.

Enrich API Responses with External Data

سكريبت http-response يثري بيانات المستخدمين باستدعاء API ثانوي:

[Script]
EnrichUsers = type=http-response, script-path=enrich.js, pattern=^https://api\.example\.com/users, requires-body=true
// enrich.js
var users = JSON.parse($response.body)
var pending = users.length
if (pending === 0) { $done({}) }

users.forEach(function(user, index) {
    $httpClient.get("https://internal-api.example.com/avatar/" + user.id,
        function(error, resp, data) {
            if (!error && resp.status === 200) {
                users[index].avatar = JSON.parse(data).url
            }
            pending--
            if (pending === 0) {
                $done({body: JSON.stringify(users)})
            }
        }
    )
})

نموذج التنفيذ

  • تعمل جميع السكريبتات على طابور تسلسلي مخصص لسلامة الخيوط.
  • كل تنفيذ سكريبت له مهلة خاصة به؛ إذا لم يتم استدعاء $done() خلال المهلة، يعامل السكريبت كتمرير.
  • يُحتفظ بمجموعة من 3 سياقات JSContext مهيأة مسبقاً؛ يُتخلص من السياق بعد كل تنفيذ ويُستبدل بآخر جديد، لذا لا تتسرب globals أبداً بين التشغيلات.
  • على iOS/tvOS، تخضع السكريبتات لحد ذاكرة 10MB؛ على macOS، 512MB.
  • السكريبتات البعيدة (مسارات HTTP/HTTPS) تُجلب عند كل تنفيذ. عندما تكون script-update-interval غير صفرية، يستطلع Chute الرابط إضافياً بطلب HEAD شرطي كل 10 دقائق؛ 0 (الافتراضي) يعطل الاستطلاع.

دمج سكريبتات الوحدات

يمكن أيضاً تعريف السكريبتات في ملفات Module (.sgmodule) تحت القسم [Script].

S. Smart Rabbit LLC © All Rights Reserved            updated 2026-07-28 17:49:04

results matching ""

    No results matching ""