कस्टम स्क्रिप्ट
बिल्ट-इन स्क्रिप्ट आम फ़्लो को कवर कर देती हैं। जब आपको कुछ ऐसा चाहिए जो वे नहीं देतीं — किसी और क्रम में कोई चरण, कोई ऐसी स्क्रीन जिसे वे कभी नहीं छूतीं, या कोई ऐसा ऐप जो न TikTok है न Instagram — तो आप उसे किसी भी भाषा में ख़ुद लिख सकते हैं और TikMatrix आपको फ़ोन सौंप देगा।
आवश्यकताएँ
कस्टम स्क्रिप्ट के लिए Pro, Team या Business प्लान चाहिए। Starter प्लान को पहुँच नहीं है।
आपके प्लान की डिवाइस संख्या ही समवर्तीता (concurrency) की सीमा भी है: Pro प्लान (20 डिवाइस) एक साथ 20 फ़ोन चला सकता है — चाहे बिल्ट-इन टास्क से, कस्टम स्क्रिप्ट से, या दोनों के मिश्रण से।
स्क्रिप्ट चलाने के दो तरीक़े
स्वतंत्र (Standalone)
प्रोग्राम आप ख़ुद चलाते हैं। 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())
एक-बार के काम, डेटा संग्रह, और उन सब चीज़ों के लिए अच्छा जिन्हें आप अपने शेड्यूलर से चलाना चाहते हैं।
प्रबंधित (Managed)
आप प्रोग्राम को 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
फिर SDK डायरेक्टरी से tikmatrix.py को अपनी स्क्रिप्ट के बग़ल में कॉपी करें। लाइब्रेरी एक ही फ़ाइल है, कोई और निर्भरता नहीं।
इसे इस्तेमाल करना अनि वार्य नहीं — API सादा JSON over 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 ऑब्जेक्ट जो प्रोग्राम के एनवायरनमेंट में मिला दिया जाता है |
| सक्षम | स्क्रिप्ट को हटाए बिना बंद करें। अक्षम स्क्रिप्ट भेजी नहीं जा सकती |
फिर स्क्रिप्ट की पंक्ति पर ▶ दबाएँ और डिवाइस चुनें — बिल्कुल किसी बिल्ट-इन स्क्रिप्ट की तरह।
AI असिस्टेंट सामान्य भाषा के विवरण से कस्टम स्क्रिप्ट तैयार कर सकता है और एक ही चरण में रजिस्टर कर सकता है। डिस्क पर कुछ भी लिखे जाने से पहले वह पूरी फ़ाइल आपको दिखाता है।
डिवाइस लीज़
एक समय में एक फ़ोन को केवल एक ही चीज़ चला सकती है। उसे लीज़ पर लेना TikMatrix को बताता है कि डिवाइस व्यस्त है, इसलिए:
- टास्क क़तार उसी स्क्रीन पर कोई टास्क नहीं भेजेगी, और
- आपके JSON-RPC कॉल एजेंट की सेहत ठीक वैसे ही रिपोर्ट करते हैं जैसे कोई बिल्ट-इन स्क्रिप्ट करती है, इसलिए वॉचडॉग को चुप एजेंट नहीं बल्कि व्यस्त एजेंट दिखता है।
लीज़ आपके प्लान का एक डिवाइस स्लॉट भी घेरती है।
लीज़ की अवधि समाप्त होती है — डिफ़ॉल्ट 120 सेकंड, अधिकतम 600। Python लाइब्रेरी इसे बैकग्राउंड थ्रेड में नवीनीकृत करती है और with ब्लॉक ख़त्म होते ही छोड़ देती है, इसलिए क्रैश हुई स्क्रिप्ट अपना डिवाइस सेकंडों में मुक्त कर देती है, न कि ऐप दोबारा शुरू करने तक पकड़े रहती है। यदि आप सीधे API कॉल कर रहे हैं तो हार्टबीट ख़ुद भेजें।
हर सक्रिय लीज़ देख सकते हैं — और ज़बरदस्ती छोड़ भी सकते हैं — सेटिंग्स → Developer API → सक्रिय डिवाइस सेशन में।
प्लेटफ़ॉर्म मोड
रजिस्टर की गई स्क्रिप्ट घोषित करती है कि उसका लक्ष्य क्या है:
Generic — डिवाइस बिना छेड़छाड़ के सौंप दिया जाता है। कोई ऐप नहीं खुलता, कोई अकाउंट स्विच नहीं होता, इनपुट मेथड की जाँच नहीं होती, और बाद में कुछ बंद नहीं किया जाता। TikTok या Instagram के अलावा कुछ भी स्वचालित करने के लिए इसका उपयोग करें।
TikTok / Instagram — आपका प्रोग्राम शुरू होने से पहले ऐप खोला जाता है और अकाउंट बदला जाता है, और अंत में ऐप बंद कर दिया जाता है — बिल्कुल बिल्ट-इन स्क्रिप्ट की तरह। TIKMATRIX_PACKAGE बताता है कि कौन-सा पैकेज तय हुआ। इसका उपयोग तब करें जब आपको ऐसा चरण जोड़ना हो जो बिल्ट-इन स्क्रिप्ट में नहीं है।
एनवायरनमेंट वे रिएबल
प्रबंधित स्क्रिप्ट को मिलते हैं:
| वेरिएबल | अर्थ |
|---|---|
TIKMATRIX_API_BASE | सर्वर URL, जैसे http://127.0.0.1:50809 |
TIKMATRIX_SESSION_ID | आपकी ओर से पहले से ली गई लीज़ |
TIKMATRIX_SERIAL | वह डिवाइस जिस पर यह टास्क भेजा गया |
TIKMATRIX_PACKAGE | तय किया गया ऐप पैकेज |
TIKMATRIX_PLATFORM | tiktok, instagram या generic |
TikMatrix.from_env() ये सब आपके लिए पढ़ लेता है।
स्वतंत्र स्क्रिप्ट को इनमें से कुछ नहीं मिलता — डिवाइस को स्पष्ट रूप से लीज़ पर लें।
अतिरिक्त एनवायरनमेंट वेरिएबल में आप जो डालते हैं वह ऊपर से मिला दिया जाता है — यही वह सामान्य तरीक़ा है जिससे एक ही रजिस्टर स्क्रिप्ट को फ़ाइल बदले बिना हर रन के लिए अलग सेटिंग दी जाती है।
Python लाइब्रेरी संदर्भ
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() | मौजूदा UI ट्री 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) | साथ आए तेज़ इनपुट IME से फ़ोकस्ड फ़ील्ड में टाइप करता है |
d.jsonrpc(method, params=None, timeout=10) | कोई भी UIAutomator2 मेथड |
d.adb(*args, timeout_ms=None) | ADB कमांड चलाता है |
d.release() | लीज़ छोड़ता है। with यह अपने आप करता है |
find डंप किए गए UI ट्री पर मिलान करता है, इसलिए जब कोई सेलेक्टर चूक जाए तो print(d.hierarchy()) करके देख सकते हैं कि उसने वास्तव में किसमें खोजा। डिवाइस व्यू का एलिमेंट इंस्पेक्टर वही ट्री दृश्य रूप में दिखाता है, जो resource-id ढूँढ़ने का आमतौर पर सबसे तेज़ तरीक़ा है।
input_text को ADB चाहिएयह साथ आए इनपुट मेथड को ब्रॉडकास्ट भेजता है, जो adb shell स े होकर जाता है। इस्तेमाल से पहले ADB पहुँच चालू करें, वरना यह 403 के साथ विफल होगा।
त्रुटियाँ
लाइब्रेरी दो अपवाद फेंकती है, दोनों RuntimeError के उपवर्ग हैं:
| अपवाद | कब |
|---|---|
DeviceBusyError | HTTP 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 कुंजी नहीं है: बाक़ी लोकल API की तरह ये एंडपॉइंट प्रमाणीकृत नहीं हैं — नेटवर्क पर इस मशीन तक पहुँच पाना ही एक्सेस कंट्रोल है। ये कोई CORS हेडर नहीं भेजते, इसलिए इन्हें ब्राउज़र के किसी पेज से नहीं बल्कि किसी प्रोग्राम (curl, Python, कोई भी सर्वर-साइड कोड) से कॉल करें।
| मेथड | पथ | उद्देश्य |
|---|---|---|
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= | मौजूदा UI ट्री XML में |
GET | /api/v1/rpc/screenshot?serial= | मौजूदा स्क्रीन PNG में |
JSON प्रतिक्रियाएँ बाक़ी लोकल API जैसा ही आवरण इस्तेमाल करती हैं — {"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 | डिवाइस पहले से लीज़ पर है, या प्लान में कोई खाली स्लॉट नहीं |
किसी और भाषा में लिखना
यहाँ कुछ भी Python-विशिष्ट नहीं है। कोई भी रनटाइम जो 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।
API से कस्टम स्क्रिप्ट चलाना
रजिस्टर की गई स्क्रिप्ट टास्क प्रबंधन API से भी शुरू की जा सकती हैं, ताकि एक स्क्रिप्ट आगे का काम क़तार में डाल सके:
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 के ज़रिए UI ऑटोमेशन इसके बिना भी चलता है।
बंद रहने पर /api/v1/rpc/adb 403 लौटाता है और बाक़ी API सामान्य रूप से काम करती रहती है। स्क्रिप्ट द्वारा चलाया गया हर ADB कमांड आपकी लॉग फ़ाइल में लिखा जाता है।
ऐसी स्क्रिप्ट लिखना जो चलती रहे
- स्क्रीन का इंतज़ार करें, उसके लिए सोएँ नहीं।
d.wait_for(...)एलिमेंट आते ही लौट आता है; तयशुदा sleep या तो ज़रूरत से धीमा है या ख़राब दिन में बहुत छोटा। - टैप से पहले जाँचें। सहमति डायलॉग या "अभी नहीं" जैसे संकेत पर
d.exists(...)की क़ीमत एक ट्री डंप है, और यह उस रन को बचा लेता है जो वरना ख़ाली जगह पर टैप कर देता। - जो किया, वह प्रिंट करें। प्रबंधित मोड में stdout ही टास्क लॉग है, और यही उस रन का एकमात्र रिकॉर्ड है जिसे कोई देख नहीं रहा था।
- दोबारा चलाना सुरक्षित बनाएँ। पुनःप्रयास पूरे प्रोग्राम को फिर से चलाता है, इसलिए पोस्ट करने वाली स्क्रिप्ट को यह जाँचना चाहिए कि उसने पहले ही पोस्ट तो नहीं कर दिया।
- एक स्क्रिप्ट, एक काम। समवर्तीता प्रति डिवाइस है, इसलिए दस फ़ोनों पर दस छोटे टास्क, दस फ़ोनों पर लूप करती एक स्क्रिप्ट से कहीं जल्दी ख़त्म होते हैं।