मुख्य कंटेंट तक स्किप करें

कस्टम स्क्रिप्ट

बिल्ट-इन स्क्रिप्ट आम फ़्लो को कवर कर देती हैं। जब आपको कुछ ऐसा चाहिए जो वे नहीं देतीं — किसी और क्रम में कोई चरण, कोई ऐसी स्क्रीन जिसे वे कभी नहीं छूतीं, या कोई ऐसा ऐप जो न 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 असिस्टेंट से लिखवाएँ

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_PLATFORMtiktok, 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 के उपवर्ग हैं:

अपवादकब
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 कुंजी नहीं है: बाक़ी लोकल 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/jsonrpcUIAutomator2 मेथड कॉल करें
POST/api/v1/rpc/adbADB कमांड चलाएँ
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 ही टास्क लॉग है, और यही उस रन का एकमात्र रिकॉर्ड है जिसे कोई देख नहीं रहा था।
  • दोबारा चलाना सुरक्षित बनाएँ। पुनःप्रयास पूरे प्रोग्राम को फिर से चलाता है, इसलिए पोस्ट करने वाली स्क्रिप्ट को यह जाँचना चाहिए कि उसने पहले ही पोस्ट तो नहीं कर दिया।
  • एक स्क्रिप्ट, एक काम। समवर्तीता प्रति डिवाइस है, इसलिए दस फ़ोनों पर दस छोटे टास्क, दस फ़ोनों पर लूप करती एक स्क्रिप्ट से कहीं जल्दी ख़त्म होते हैं।

टिप्पणियाँ और सीमाएँ

  • कमांड सीधे चलाया जाता है, शेल के ज़रिए नहीं, इसलिए && और | ऑपरेटर नहीं बल्कि आर्ग्युमेंट माने जाते हैं। शेल जैसा व्यवहार चाहिए तो cmd /c "..." (Windows) या sh -c "..." (macOS) रजिस्टर करें।
  • जिन पथों में स्पेस हो उन्हें उद्धरण में रखें: "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 → सक्रिय डिवाइस सेशन देखें — या आपके प्लान के सभी डिवाइस स्लॉट चल रहे टास्क ले चुके हैं।

लंबे चरण के बीच में लीज़ समाप्त हो जाती है डिफ़ॉल्ट TTL 120 सेकंड है और लाइब्रेरी उसे बैकग्राउंड में नवीनीकृत करती है, इसलिए आम तौर पर इसका मतलब है कि स्क्रिप्ट ने अपने मुख्य थ्रेड को TTL से ज़्यादा समय तक रोके रखा। ttl_secs बढ़ाएँ (अधिकतम 600), या लंबा काम उस थ्रेड से हटाएँ।

d.adb(...) 403 के साथ विफल होता है ADB पहुँच बंद है। सेटिंग्स → Developer API → ADB कमांड की अनुमति दें से चालू करें।

सेलेक्टर कभी मेल नहीं खाता print(d.hierarchy()) वही ट्री दिखाता है जिसमें find ने खोजा था। टेक्स्ट का मिलान सटीक होता है, इसलिए आख़िर में एक अतिरिक्त स्पेस या अनूदित लेबल आम कारण है; text के बजाय resource_id से मिलान ज़्यादा स्थिर है।

टास्क विफल दिखता है पर फ़ोन ठीक लगता है टास्क लॉग पढ़ें। शून्येतर एग्ज़िट — जिसमें सफल रन के अंत में आया अनहैंडल्ड अपवाद भी शामिल है — टास्क को विफल कर देता है, भले ही ऑटोमेशन ने काम कर दिया हो।

आगे क्या