إنتقل إلى المحتوى الرئيسي

النصوص البرمجية المخصصة

تغطي النصوص المدمجة المسارات الشائعة. وعندما تحتاج إلى شيء لا توفره — خطوة بترتيب مختلف، أو شاشة لا تلمسها أبدًا، أو تطبيق ليس TikTok ولا Instagram — يمكنك كتابته بنفسك بأي لغة، ويسلّمك TikMatrix الهاتف.

المتطلبات

متطلب الترخيص

تتطلب النصوص المخصصة خطة Pro أو Team أو Business. خطة Starter لا تملك صلاحية الوصول.

عدد الأجهزة في خطتك هو أيضًا حد التزامن: خطة Pro (20 جهازًا) يمكنها تشغيل 20 هاتفًا في وقت واحد، سواء عبر المهام المدمجة أو النصوص المخصصة أو مزيج منهما.

طريقتان لتشغيل النص

مستقل

أنت من يشغّل برنامجك. TikMatrix يعيرك الأجهزة فقط.

from tikmatrix import TikMatrix

client = TikMatrix()

for device in client.devices():
if device["busy"]:
continue
with client.device(device["serial"], label="my crawler") as d:
d.press("home")
print(d.info())

مناسب للمهام لمرة واحدة، وجمع البيانات، وكل ما تريد تشغيله من مجدولك الخاص.

مُدار

تسجّل البرنامج داخل TikMatrix فيصبح مهمة كأي مهمة أخرى: طابور المهام، والتزامن حسب الخطة، وإعادة المحاولة التلقائية، وسجل المهام، وقوالب الجدولة. يحجز TikMatrix الجهاز قبل بدء برنامجك، ويمرّر معرّف الحجز عبر بيئة التشغيل.

from tikmatrix import TikMatrix

with TikMatrix.from_env() as d: # الجهاز محجوز مسبقًا
d.click(text="Log in")
print("done") # هذا السطر ينتهي في سجل المهمة

مناسب لكل ما تريد تشغيله بشكل متكرر أو مجدول أو عبر أجهزة كثيرة.

أيهما تختار

مستقلمُدار
من يبدأ التشغيلأنتطابور مهام TikMatrix
حجز الجهازتحصل عليه بنفسكمحجوز بالفعل عند البدء
إعادة المحاولة والجدولة والسجلتبنيها بنفسكمتوفرة
التشغيل على أجهزة كثيرةتكتب الحلقة بنفسكمهمة لكل جهاز، بالتوازي
الأنسب لـالاستكشاف، الزواحف، المهام لمرة واحدةكل ما تريد تكراره

يمكنك البدء بالوضع المستقل ريثما تضبط المسار، ثم تسجيل الملف نفسه كنص مُدار — السطر الوحيد الذي يتغير هو TikMatrix.from_env().

البداية

1. ثبّت مكتبة العميل

pip install requests

ثم انسخ tikmatrix.py من دليل SDK بجانب نصك البرمجي. المكتبة ملف واحد بلا اعتماديات أخرى.

لست مضطرًا لاستخدامها — الواجهة مجرد JSON عبر HTTP، ونقاط النهاية الخام موثّقة أدناه.

2. اكتب النص

from tikmatrix import TikMatrix

client = TikMatrix()
with client.device("192.168.1.5:5555") as d:
d.press("home")
d.adb("shell", "am", "start", "-a", "android.settings.SETTINGS")
d.wait_for(text="Settings", timeout=15)
d.screenshot("settings.png")

شغّله وTikMatrix مفتوح والهاتف موصول. إن طبع قاموس معلومات الجهاز فكل شيء متصل بشكل صحيح.

3. سجّله (الوضع المُدار فقط)

اذهب إلى الأجهزة ← النصوص المخصصة ← إضافة نص:

الحقلالمعنى
الاسميظهر في قائمة النصوص وفي سجل المهام
الأمرسطر البرنامج المراد تشغيله، مثل python C:/scripts/my_flow.py
دليل العملاختياري. المكان الذي يبدأ منه البرنامج
المنصةراجع أوضاع المنصة أدناه
المهلةعدد الثواني قبل إنهاء النص واعتبار المهمة فاشلة. الافتراضي 1800
متغيرات بيئة إضافيةكائن JSON اختياري يُدمج في بيئة البرنامج
مفعّللإيقاف نص دون حذفه. النص المعطّل لا يمكن إرساله للتنفيذ

ثم اضغط ▶ في صف النص واختر أجهزتك، تمامًا كما مع أي نص مدمج.

دع المساعد يكتبه لك

يستطيع المساعد الذكي صياغة نص مخصص انطلاقًا من وصف بلغة عادية وتسجيله في خطوة واحدة. وهو يعرض عليك الملف كاملًا قبل كتابة أي شيء على القرص.

حجوزات الأجهزة

لا يمكن التحكم في الهاتف إلا من جهة واحدة في الوقت نفسه. حجزه يخبر TikMatrix أن الجهاز مشغول، وبالتالي:

  • لن يرسل طابور المهام مهمة إلى الشاشة نفسها، و
  • ستُبلغ استدعاءات JSON-RPC عن صحة الوكيل تمامًا كما يفعل نص مدمج، فيرى المراقب وكيلًا مشغولًا لا وكيلًا صامتًا.

كما يستهلك الحجز مقعد جهاز واحدًا من خطتك.

تنتهي صلاحية الحجوزات — 120 ثانية افتراضيًا، و600 كحد أقصى. تجدّد مكتبة بايثون حجزك في خيط خلفي وتحرّره عند انتهاء كتلة with، فينعتق الجهاز خلال ثوانٍ إذا انهار النص بدل بقائه محجوزًا حتى تعيد تشغيل التطبيق. وإن كنت تستدعي الواجهة مباشرة فعليك إرسال نبضات الحياة بنفسك.

يمكنك رؤية كل الحجوزات النشطة — وتحرير أي منها قسرًا — من الإعدادات ← Developer API ← جلسات الأجهزة النشطة.

أوضاع المنصة

يعلن النص المسجّل عن هدفه:

Generic — يُسلَّم الجهاز كما هو. لا يُفتح أي تطبيق، ولا تبديل حسابات، ولا فحص لطريقة الإدخال، ولا يُغلق شيء بعد الانتهاء. استخدمه لأتمتة أي شيء غير TikTok أو Instagram.

TikTok / Instagram — يُفتح التطبيق ويُبدَّل الحساب قبل بدء برنامجك، ويُغلق التطبيق عند الانتهاء، تمامًا كما مع نص مدمج. ويخبرك TIKMATRIX_PACKAGE بالحزمة التي جرى تحديدها. استخدمه لإضافة خطوة لا تغطيها النصوص المدمجة.

متغيرات البيئة

يستقبل النص المُدار:

المتغيرالمعنى
TIKMATRIX_API_BASEعنوان الخادم، مثل http://127.0.0.1:50809
TIKMATRIX_SESSION_IDالحجز المحفوظ لك بالفعل
TIKMATRIX_SERIALالجهاز الذي أُرسلت إليه هذه المهمة
TIKMATRIX_PACKAGEحزمة التطبيق المحدَّدة
TIKMATRIX_PLATFORMtiktok أو instagram أو generic

تقرأ TikMatrix.from_env() كل ذلك نيابة عنك.

النصوص المستقلة لا تحصل على أي منها — احجز جهازًا صراحةً بدلًا من ذلك.

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

مرجع مكتبة بايثون

TikMatrix — الاتصال

الاستدعاءما يفعله
TikMatrix(base_url=None, timeout=30.0)يتصل. يعود إلى TIKMATRIX_API_BASE ثم http://127.0.0.1:50809
client.devices()الأجهزة المتصلة، كل منها بـ serial وreal_serial وbusy
client.sessions()كل الحجوزات النشطة، بما فيها ما لا تملكه هذه العملية
client.device(serial, label=..., ttl_secs=120)يحجز جهازًا ويعيد Device
TikMatrix.from_env()يتبنّى الجهاز الذي بدأ به نص مُدار

Device — الهاتف

الاستدعاءما يفعله
d.info()معلومات الجهاز من UIAutomator2
d.window_size()(العرض، الارتفاع)
d.screenshot(path=None)بايتات PNG، وتُكتب في path اختياريًا
d.hierarchy()شجرة الواجهة الحالية بصيغة XML
d.find(text=, resource_id=, description=, class_name=)العقد المطابقة، كل منها بـ bounds وcenter
d.exists(**criteria)هل يوجد تطابق
d.wait_for(timeout=10.0, interval=1.0, **criteria)ينتظر حتى يظهر ثم يعيده
d.click(timeout=10.0, **criteria)ينتظر عنصرًا ثم ينقر مركزه
d.click_xy(x, y)ينقر إحداثية
d.swipe(sx, sy, ex, ey, steps=20)يسحب
d.press(key)back وhome وrecent وenter
d.input_text(text)يكتب في الحقل النشط عبر لوحة الإدخال السريع المرفقة
d.jsonrpc(method, params=None, timeout=10)أي دالة من UIAutomator2
d.adb(*args, timeout_ms=None)ينفّذ أمر ADB
d.release()يحرّر الحجز. وwith يفعل ذلك عنك

يطابق find على شجرة الواجهة المستخرجة، لذا حين يخطئ المحدِّد يمكنك تنفيذ print(d.hierarchy()) لترى بالضبط ما جرى البحث فيه. ويعرض فاحص العناصر في واجهة الجهاز الشجرة نفسها بصريًا، وهو عادةً أسرع طريقة للعثور على resource-id.

input_text يحتاج إلى ADB

يرسل بثًا إلى لوحة الإدخال المرفقة عبر adb shell. فعّل وصول ADB قبل استخدامه، وإلا فشل برمز 403.

الأخطاء

ترفع المكتبة استثناءين، وكلاهما يرث من RuntimeError:

الاستثناءمتى
DeviceBusyErrorHTTP 409 — الجهاز محجوز بالفعل، أو لا مقعد جهاز شاغر في خطتك
TikMatrixErrorكل ما عدا ذلك: خطة أدنى من اللازم، حجز منتهٍ، ADB معطّل، محدِّد لم يطابق أبدًا
from tikmatrix import TikMatrix, TikMatrixError, DeviceBusyError

client = TikMatrix()
try:
with client.device("192.168.1.5:5555") as d:
d.click(text="Log in", timeout=20)
except DeviceBusyError:
print("هذا الهاتف مشغول لدى جهة أخرى — جرّب غيره")
except TikMatrixError as exc:
print("فشل:", exc)

في النص المُدار يكون ترك الاستثناء يخرج هو التصرف الصحيح عادةً: فالخروج بقيمة غير صفرية يعلّم المهمة كفاشلة، ويصل التتبّع إلى سجل المهمة.

نقاط نهاية HTTP

تحتاج عمليات الجهاز إلى ترويسة x-session-id تشير إلى حجز نشط. لا يوجد مفتاح API: فكما هي حال بقية الواجهة المحلية، هذه النقاط غير مصادَق عليها — والقدرة على الوصول إلى الجهاز عبر الشبكة هي ضابط الوصول. وهي لا ترسل أي ترويسات CORS، لذا استدعِها من برنامج (curl أو بايثون أو أي كود من جهة الخادم) لا من صفحة في المتصفح.

الطريقةالمسارالغرض
GET/api/v1/rpc/devicesسرد الأجهزة المتصلة وما إذا كان كل منها مشغولًا
POST/api/v1/rpc/sessionحجز جهاز ← session_id
POST/api/v1/rpc/session/{id}/heartbeatتمديد الحجز
DELETE/api/v1/rpc/session/{id}تحرير الحجز
GET/api/v1/rpc/sessionسرد الحجوزات النشطة
POST/api/v1/rpc/jsonrpcاستدعاء دالة UIAutomator2
POST/api/v1/rpc/adbتنفيذ أمر ADB
GET/api/v1/rpc/hierarchy?serial=شجرة الواجهة الحالية بصيغة XML
GET/api/v1/rpc/screenshot?serial=الشاشة الحالية بصيغة PNG

تستخدم استجابات JSON الغلاف نفسه المستخدم في بقية الواجهة المحلية — {"code": 0, "message": "success", "data": ...} — مع code غير صفري عند الفشل. أما hierarchy وscreenshot فتعيدان المحتوى الخام.

مثال

# حجز جهاز
curl -X POST http://127.0.0.1:50809/api/v1/rpc/session \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.5:5555","label":"curl test","ttl_secs":120}'

# {"code":0,"message":"success","data":{"session_id":"ff3ae079-...","serial":"192.168.1.5:5555", ...}}

# التحكم به
curl -X POST http://127.0.0.1:50809/api/v1/rpc/jsonrpc \
-H "x-session-id: ff3ae079-..." \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.5:5555","method":"deviceInfo","params":[]}'

# إبقاء الحجز حيًا أثناء العمل
curl -X POST http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-.../heartbeat \
-H "Content-Type: application/json" \
-d '{"ttl_secs":120}'

# إعادته
curl -X DELETE http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-...

الأخطاء

الحالةالمعنى
403خطة أدنى من Pro، أو لا حجز، أو حجز منتهٍ، أو وصول ADB معطّل
409الجهاز محجوز بالفعل، أو لا مقعد جهاز شاغر في خطتك

الكتابة بلغة أخرى

لا شيء هنا خاص ببايثون. تصلح أي بيئة تشغيل قادرة على إرسال طلب HTTP — فعقد الوضع المُدار هو فقط: «اقرأ ثلاثة متغيرات بيئة، واخرج بالقيمة 0 عند النجاح».

// my_flow.js — سجّله بـ: node C:/scripts/my_flow.js
const base = process.env.TIKMATRIX_API_BASE || "http://127.0.0.1:50809";
const serial = process.env.TIKMATRIX_SERIAL;
const session = process.env.TIKMATRIX_SESSION_ID;

async function jsonrpc(method, params = []) {
const res = await fetch(`${base}/api/v1/rpc/jsonrpc`, {
method: "POST",
headers: { "content-type": "application/json", "x-session-id": session },
body: JSON.stringify({ serial, method, params }),
});
const body = await res.json();
if (!res.ok || body.code !== 0) throw new Error(body.message || res.statusText);
return body.data;
}

console.log(await jsonrpc("deviceInfo"));

إن لم يكن المفسّر ضمن PATH فاكتب مساره الكامل في حقل الأمر، مثل C:/Program Files/nodejs/node.exe C:/scripts/my_flow.js.

تشغيل نص مخصص من الواجهة البرمجية

يمكن أيضًا تشغيل النصوص المسجّلة عبر واجهة إدارة المهام، فيستطيع نص واحد أن يضع عملًا لاحقًا في الطابور:

curl -X POST http://127.0.0.1:50809/api/v1/task \
-H "Content-Type: application/json" \
-d '{
"serials": ["192.168.1.5:5555"],
"script_name": "custom_script",
"script_config": {
"custom_script_id": 1,
"custom_script_platform": "generic"
}
}'

وcustom_script_id هو معرّف النص الذي سجّلته.

وصول ADB

يمنح /api/v1/rpc/adb نصوصك صدفة على الجهاز — وتحتاجها لرفع الوسائط وتثبيت ملفات APK وتغيير إعدادات النظام. ولأنها صدفة كاملة على نقطة نهاية بلا مفتاح API، فهي معطّلة عند التسليم. فعّلها من الإعدادات ← Developer API ← السماح بأوامر ADB حين يكون لديك نص يحتاجها؛ أما أتمتة الواجهة عبر /rpc/jsonrpc فتعمل بدونها.

وأثناء تعطيلها يجيب /api/v1/rpc/adb بالرمز 403 وتبقى بقية الواجهة تعمل. ويُكتب كل أمر ADB ينفّذه أي نص في ملف السجل لديك.

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

  • انتظر الشاشة ولا تنم من أجلها. يعود d.wait_for(...) فور ظهور العنصر؛ أما النوم الثابت فإما أبطأ من اللازم أو أقصر من اللازم في يوم سيئ.
  • تحقّق قبل النقر. استدعاء d.exists(...) على نافذة موافقة أو تنبيه «ليس الآن» يكلّف استخراج شجرة واحدة وينقذ تشغيلة كانت ستنقر في الفراغ.
  • اطبع ما فعلته. في الوضع المُدار يكون stdout هو سجل المهمة، وهو الأثر الوحيد لتشغيلة لم يراقبها أحد.
  • اجعل إعادة التشغيل آمنة. إعادة المحاولة تعيد تنفيذ البرنامج كاملًا، لذا ينبغي للنص الذي ينشر أن يتحقق مما إذا كان قد نشر بالفعل بدل افتراض أنه يبدأ من الصفر.
  • نص واحد لمهمة واحدة. التزامن محسوب لكل جهاز، فعشر مهام صغيرة على عشرة هواتف تنتهي أسرع بكثير من نص واحد يدور على عشرة هواتف.

ملاحظات وحدود

  • يُنفَّذ الأمر مباشرةً لا عبر صدفة، لذا يُعامَل && و| كوسيطات لا كمعاملات. سجّل cmd /c "..." (ويندوز) أو sh -c "..." (ماك) إن أردت سلوك الصدفة.
  • ضع المسارات التي تحوي مسافات بين علامتي اقتباس: "C:/Program Files/Python/python.exe" my_script.py.
  • النص الذي يتجاوز مهلته يُنهى وتُعلَّم المهمة كفاشلة.
  • رمز الخروج غير الصفري يعلّم المهمة كفاشلة؛ وكل ما يكتبه النص إلى stdout وstderr ينتهي في سجل المهمة.
  • تعمل النصوص بالصلاحيات نفسها التي يعمل بها TikMatrix. لا تسجّل إلا برامج كتبتها بنفسك أو تثق بها.

استكشاف الأخطاء

API access requires Pro or higher plan (403) الترخيص على هذا الجهاز هو Starter أو غير نشط. راجع الإعدادات ← الترخيص.

رفض الاتصال على 127.0.0.1:50809 TikMatrix غير مشغّل، أو يعمل بحساب مستخدم آخر. الخادم موجود فقط ما دام التطبيق مفتوحًا.

409 عند كل محاولة حجز إما أن الهاتف مشغول فعلًا — راجع الإعدادات ← Developer API ← جلسات الأجهزة النشطة — أو أن كل مقاعد الأجهزة في خطتك مشغولة بمهام قيد التنفيذ.

ينتهي الحجز في منتصف خطوة طويلة المهلة الافتراضية 120 ثانية والمكتبة تجدّدها في الخلفية، لذا يعني هذا غالبًا أن النص حجب خيطه الرئيسي مدة أطول من المهلة. ارفع ttl_secs (حتى 600)، أو انقل العمل الطويل خارج ذلك الخيط.

d.adb(...) يفشل بالرمز 403 وصول ADB معطّل. فعّله من الإعدادات ← Developer API ← السماح بأوامر ADB.

محدِّد لا يطابق أبدًا يعرض print(d.hierarchy()) الشجرة التي بحث فيها find بالضبط. والنص يُطابَق حرفيًا، لذا فالسبب المعتاد مسافة زائدة أو تسمية مترجَمة؛ والمطابقة عبر resource_id أثبت من المطابقة عبر text.

المهمة معلَّمة كفاشلة لكن الهاتف يبدو سليمًا اقرأ سجل المهمة. فالخروج بقيمة غير صفرية — بما في ذلك استثناء غير مُلتقَط في نهاية تشغيلة ناجحة — يُفشل المهمة حتى لو نجحت الأتمتة نفسها.

الخطوات التالية