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

एपीआई उदाहरण

प्रत्येक एक्सटेंशन फ्लो के लिए सही अनुरोध आकार को कॉपी करने के लिए इस पृष्ठ का उपयोग करें।

  • आईफ्रेम ब्रिज के उदाहरण postMessage क्रियाओं का उपयोग करते हैं जैसे कि session.get, state.get और files.get
  • विशेषाधिकार प्राप्त उदाहरण Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY और x-chastify-main-token के साथ आपके स्वयं के एक्सटेंशन बैकएंड का उपयोग करते हैं।
  • डेवलपर एपीआई कुंजी को कभी भी आईफ्रेम या ब्राउज़र कोड पर न भेजें।
info

आईफ्रेम ब्रिज का उपयोग यूआई बूटस्ट्रैप और कम जोखिम वाले सेशन ऑपरेशन्स के लिए किया जाता है। इसका उपयोग कॉन्टेक्स्ट पढ़ने, एक्सटेंशन के स्वामित्व वाली स्थिति को स्टोर करने और फ़ाइल यूआरएल को हल करने के लिए करें।

caution

ब्राउज़र आईफ़्रेम कोड उपयोगकर्ता द्वारा नियंत्रित होता है। समय लागू करने/हटाने, कार्यों को पूरा करने, अनलॉक ब्लॉकर हटाने, रनटाइम फ़ाइलें अपलोड/हटाने, सूचनाएं भेजने, लॉग लिखने या उपकरणों को कमांड देने के लिए आईफ़्रेम ब्रिज अनुरोधों का उपयोग न करें।

अनुरोध और प्रतिक्रिया प्रारूप

सुरक्षित आईफ्रेम ब्रिज क्रियाएं इस ब्रिज अनुरोध लिफाफे के अंदर भेजी जाती हैं:

{
"type": "chastify:ext:req", // required
"v": 1, // protocol version
"id": "req-123", // your unique request id
"nonce": "from-iframe-hash",
"action": "session.get",
"payload": {}
}

और आपको प्राप्त होता है:

{
"type": "chastify:ext:resp",
"v": 1,
"id": "req-123", // same id you sent
"ok": true,
"data": {}
}

यदि ok, false के बराबर है, तो error.code और error.message की जाँच करें।

बैकएंड-ओनली उदाहरण आपके सर्वर से सामान्य HTTPS अनुरोधों का उपयोग करते हैं। इन्हें iframe ब्रिज के माध्यम से नहीं भेजा जाता है।

सत्र और संदर्भ

session.get

लगभग हर एक्सटेंशन फ्लो में सबसे पहले इसका उपयोग करें।

यह क्या करता है:

  • यह सत्यापित करता है कि आपका ब्रिज कनेक्शन काम कर रहा है।
  • यह सेशन कॉन्टेक्स्ट (लॉक स्थिति, भूमिका, एक्सटेंशन कॉन्फ़िगरेशन, क्षमताएं) लौटाता है।
  • यह डिवाइस की क्षमता संबंधी जानकारी लौटाता है जिसका उपयोग आपका यूआई आपके बैकएंड से device.command को कॉल करने के लिए कहने से पहले कर सकता है।

इसका उपयोग किस लिए किया जाता है:

  • अपने यूआई को बूटस्ट्रैप करना।
  • भूमिका और अनुमतियों के आधार पर सुविधाओं को सक्षम/अक्षम करना।
  • डिवाइस कंट्रोल प्रदर्शित करने से पहले समर्थित डिवाइस कमांड की जाँच करना।

उदाहरण एक्शन पेलोड:

{
"action": "session.get",
"payload": {}
}

उदाहरण session.get प्रतिक्रिया अंश (रनटाइम लॉक डेटा):

{
"ok": true,
"data": {
"lockData": {
"frozen": false,
"unlockable": false,
"trusted": true,
"taskAssigned": true,
"timeLockedSeconds": 1420,
"timeRemainingSeconds": 27800,
"maxTimeRemainingSeconds": 86400,
"taskPoints": 12,
"taskPointsRequired": 20,
"lockTitle": "Weekend Challenge",
"wearerUsername": "alice",
"keyholderUsername": "kh_bob",
"wearerLastSeenTimestamp": 1739640505123,
"keyholderLastSeenTimestamp": null
}
}
}

गोपनीयता संबंधी नोट्स:

  • wearerLastSeenTimestamp / keyholderLastSeenTimestamp केवल तभी लौटाए जाते हैं जब उस उपयोगकर्ता के पास showOnlineStatus !== false हो।
  • यदि ऑनलाइन स्थिति दृश्यता अक्षम है, तो ये फ़ील्ड null हैं।

बैकएंड एक्सटेंशन फ्लो

ये उदाहरण सुरक्षित उत्पादन पद्धति को दर्शाते हैं:

  1. आईफ्रेम हैश पेलोड से mainToken और sessionId पढ़ता है।
  2. आईफ्रेम उन्हें आपके बैकएंड पर भेजता है।
  3. आपका बैकएंड आपके गेम/टास्क/बिजनेस की स्थिति को मान्य करता है।
  4. आपका बैकएंड Chastify को ऐप-स्कोप डेवलपर API कुंजी और x-chastify-main-token के साथ कॉल करता है।

प्रमाणीकरण के लिए अकेले sessionId का उपयोग न करें। mainToken को ब्राउज़र-दृश्यमान लॉन्च संदर्भ के रूप में मानें, और अपनी डेवलपर API कुंजी को केवल बैकएंड के लिए गुप्त कुंजी के रूप में मानें।

warning

Chastify को कॉल करने से पहले आपके बैकएंड को अपने गेम/टास्क की स्थिति को मान्य करना होगा। iframe से mainToken और sessionId पास करने से केवल खुले हुए एक्सटेंशन सेशन की पहचान होती है; यह साबित नहीं होता कि उपयोगकर्ता ने कोई चुनौती पूरी की है।

सेशन कॉन्टेक्स्ट को सुरक्षित रूप से प्राप्त करें

आपका iframe UI बूटस्ट्रैप के लिए सुरक्षित ब्रिज session.get का उपयोग कर सकता है। यदि आपके बैकएंड को किसी विशेषाधिकार प्राप्त कार्रवाई को लागू करने से पहले समान संदर्भ की आवश्यकता है, तो दोनों क्रेडेंशियल्स का उपयोग करके इसे अपने बैकएंड से प्राप्त करें।

आईफ्रेम:

const hash = JSON.parse(decodeURIComponent(window.location.hash.slice(1)));

await fetch("/api/my-extension/session-context", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
mainToken: hash.mainToken,
sessionId: hash.sessionId
})
});

आपका बैकएंड:

app.post("/api/my-extension/session-context", async (req, res) => {
const { mainToken, sessionId } = req.body;

const response = await fetch(
`https://chastify.net/api/extensions/sessions/${encodeURIComponent(sessionId)}`,
{
headers: {
Authorization: `Bearer ${process.env.CHASTIFY_APP_DEVELOPER_KEY}`,
"x-chastify-main-token": mainToken
}
}
);

if (!response.ok) {
return res.status(response.status).json(await response.json());
}

const context = await response.json();

res.json({
role: context.role,
config: context.extensionConfig,
lockData: context.lockData
});
});

एक्सटेंशन बैकएंड से समय लागू करें

ब्राउज़र आपके बैकएंड से इनाम या दंड देने का अनुरोध कर सकता है, लेकिन ब्राउज़र को यह तय नहीं करना चाहिए कि कार्रवाई वैध है या नहीं। कार्रवाई की पुष्टि पहले सर्वर-साइड पर करें।

app.post("/api/my-extension/apply-reward", async (req, res) => {
const { mainToken, sessionId, runId } = req.body;

const run = await db.gameRuns.findUnique({ where: { id: runId } });
if (!run || run.sessionId !== sessionId || !run.serverVerifiedWin) {
return res.status(403).json({ error: "game_not_verified" });
}

const response = await fetch(
`https://chastify.net/api/extensions/sessions/${encodeURIComponent(sessionId)}/action`,
{
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Bearer ${process.env.CHASTIFY_APP_DEVELOPER_KEY}`,
"x-chastify-main-token": mainToken
},
body: JSON.stringify({
name: "remove_time",
params: 300
})
}
);

if (!response.ok) {
return res.status(response.status).json(await response.json());
}

res.json(await response.json());
});

दंड के लिए add_time और पुरस्कार के लिए remove_time का प्रयोग करें।

सर्वर-सत्यापित गेम पूर्णता

साइमन सेज़ जैसे गेम के लिए, क्लाइंट द्वारा बताई गई जीत पर भरोसा न करें। सर्वर-साइड पर रन बनाएं, अपेक्षित अनुक्रम या उसका हैश स्टोर करें, और Chastify को कॉल करने से पहले सबमिट किए गए इनपुट को सत्यापित करें।

ब्राउज़र पर दिखाई देने वाला मेमोरी गेम यह साबित नहीं कर सकता कि किसी व्यक्ति ने ईमानदारी से खेला है, क्योंकि गेम को प्रदर्शित करने के लिए ब्राउज़र को अनुक्रम प्राप्त करना आवश्यक है। सर्वर सत्यापन अभी भी जाली Chastify परिवर्तनों को रोकता है और आपके बैकएंड को पुरस्कार या दंड लागू करने से पहले रन आईडी, समाप्ति तिथि, कठिनाई स्तर, लय, स्कोरिंग और रीप्ले सुरक्षा को लागू करने की अनुमति देता है।

app.post("/api/simon/runs", async (req, res) => {
const { mainToken, sessionId } = req.body;
await verifySessionLaunch({ mainToken, sessionId });

const sequence = createSimonSequence();

const run = await db.simonRuns.create({
data: {
sessionId,
sequenceHash: hashSequence(sequence),
expiresAt: new Date(Date.now() + 5 * 60_000)
}
});

res.json({
runId: run.id,
sequence
});
});

app.post("/api/simon/runs/:runId/complete", async (req, res) => {
const { mainToken, sessionId, input } = req.body;
await verifySessionLaunch({ mainToken, sessionId });

const run = await db.simonRuns.findUnique({ where: { id: req.params.runId } });

if (!run || run.sessionId !== sessionId || run.expiresAt < new Date()) {
return res.status(403).json({ error: "run_invalid" });
}

const won = hashSequence(input) === run.sequenceHash;
await db.simonRuns.update({
where: { id: run.id },
data: { completedAt: new Date(), serverVerifiedWin: won }
});

if (won) {
await fetch(`https://chastify.net/api/extensions/sessions/${encodeURIComponent(sessionId)}/requirements/progress`, {
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Bearer ${process.env.CHASTIFY_APP_DEVELOPER_KEY}`,
"x-chastify-main-token": mainToken
},
body: JSON.stringify({
key: "simon_says_wins",
amount: 1
})
});
}

res.json({ won });
});

रन स्टोरेज स्कीम पूरी तरह से आपकी है। verifySessionLaunch को ZXQ2ZXQ पर भरोसा करने से पहले आपके ऐप-स्कोप डेवलपर API कुंजी और x-chastify-main-token के साथ Chastify को कॉल करना चाहिए। महत्वपूर्ण नियम यह है कि Chastify में बदलाव तभी होते हैं जब आपका बैकएंड लॉन्च और परिणाम को सत्यापित कर लेता है।

निर्धारित आवश्यकताएँ

आपके बैकएंड के पास शेड्यूल, कैडेंस चेक और प्रूफ वैलिडेशन का स्वामित्व है। Chastify का उपयोग केवल विश्वसनीय प्रगति को रिकॉर्ड करने या बैकएंड द्वारा आवश्यकता पूरी होने का निर्णय लेने के बाद अनलॉक ब्लॉकर को अपडेट करने के लिए करें।

async function recordDailyRequirementProgress({ sessionId, mainToken, userId }) {
const completed = await db.dailyCheckins.exists({
where: {
userId,
day: new Date().toISOString().slice(0, 10),
verified: true
}
});

if (!completed) return;

await fetch(`https://chastify.net/api/extensions/sessions/${encodeURIComponent(sessionId)}/requirements/progress`, {
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Bearer ${process.env.CHASTIFY_APP_DEVELOPER_KEY}`,
"x-chastify-main-token": mainToken
},
body: JSON.stringify({
key: "daily_checkin",
amount: 1
})
});
}

वर्तमान में स्थापित एक्सटेंशन सेशन API के लिए x-chastify-main-token में एक वैध iframe लॉन्च टोकन की आवश्यकता होती है; लॉन्च टोकन वर्तमान में 10 घंटे बाद समाप्त हो जाते हैं। उस टोकन की समय सीमा समाप्त होने के बाद चलने वाले निर्धारित कार्यों के लिए, अपना स्वयं का लंबित प्रमाण संग्रहीत करें और अगले वैध एक्सटेंशन लॉन्च पर प्रगति सबमिट करें, या बिना किसी हस्तक्षेप के पृष्ठभूमि में कार्य करने के लिए डिज़ाइन किए गए किसी फर्स्ट-पार्टी/बिल्ट-इन सर्वर फ़्लो का उपयोग करें।

caution

सिर्फ इसलिए कि शेड्यूल्ड जॉब आपके सर्वर पर चल रही हैं, उन्हें विश्वसनीय न समझें। आवश्यकता प्रगति को रिकॉर्ड करने से पहले जॉब को सर्वर-साइड प्रमाण, कैडेंस जांच, रीप्ले सुरक्षा और एक वैध Chastify प्राधिकरण पथ की आवश्यकता होती है।

सूचनाएं

notifications.custom

इसका उपयोग अपने एक्सटेंशन बैकएंड से पहनने वाले, कुंजीधारक या दोनों को कस्टम एक्सटेंशन अधिसूचना भेजने के लिए करें।

अंतिम बिंदु:

POST /api/extensions/sessions/:sessionId/notifications/custom
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH

उदाहरण बॉडी:

{
"title": "Extension Reminder",
"message": "Your next challenge is ready.",
"showPageOverlay": false,
"target": "both"
}

टिप्पणियाँ:

  • showPageOverlay डिफ़ॉल्ट रूप से false पर सेट हो जाता है।
  • target डिफ़ॉल्ट रूप से wearer पर सेट हो जाता है।
  • API extension_app_message प्रकार की अधिसूचना बनाता है।

विस्तार राज्य

एक्सटेंशन स्टेट, वर्तमान लॉक सेशन के लिए आपके एक्सटेंशन के स्वामित्व वाला JSON डेटा है। स्टेट राइट्स केवल बैकएंड-आधारित हैं और इसके लिए ऐप-स्कोप डेवलपर API कुंजी और सेशन mainToken की आवश्यकता होती है। Iframe state.get के साथ स्टेट को पढ़ सकते हैं, लेकिन वे सीधे स्टेट नहीं लिख सकते।

state.put

यह क्या करता है:

  • यह संपूर्ण स्टेट ऑब्जेक्ट को नए data ऑब्जेक्ट से बदल देता है।
  • इसके लिए बैकएंड क्रेडेंशियल की आवश्यकता है।

कब उपयोग करें:

  • प्रारंभिक सेव।
  • जब आपके पास पहले से ही पूरी तरह से नई स्थिति मौजूद हो तो उसे पूरी तरह से ओवरराइट कर दें।

उदाहरण:

curl -X PUT "https://chastify.net/api/extensions/sessions/$SESSION_ID/state" \
-H "Authorization: Bearer $DEVELOPER_KEY" \
-H "x-chastify-main-token: $MAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"counter": 1,
"notes": "first test"
}
}'

क्षेत्र संबंधी टिप्पणियाँ:

  • payload.data: कोई भी मान्य JSON मान/ऑब्जेक्ट जिसकी आपके एक्सटेंशन को आवश्यकता है।
  • Avoid Mongo-unsafe key names ($ prefix or keys containing .).
  • स्टेट सेशन-स्कोपेड है और एक्सटेंशन ऐप के stateMaxBytes द्वारा आकार-सीमित है, जो डिफ़ॉल्ट रूप से 64 KiB है।
  • स्टेट में फ़ाइल आईडी स्टोर करें, बाइनरी फ़ाइलें या हस्ताक्षरित यूआरएल नहीं। मीडिया रेंडर करने से पहले हस्ताक्षरित यूआरएल को रीफ़्रेश करने के लिए files.get का उपयोग करें।

state.patch

यह क्या करता है:

  • मौजूदा स्थिति पर JSON मर्ज पैच लागू करता है।
  • केवल परिवर्तित चाबियां ही भेजनी होंगी।
  • इसके लिए बैकएंड क्रेडेंशियल की आवश्यकता है।

कब उपयोग करें:

  • उपयोगकर्ता की परस्पर क्रियाओं से प्राप्त होने वाले क्रमिक अपडेट।
  • सभी सामग्री को दोबारा भेजे बिना केवल एक फ़ील्ड को अपडेट करना।

उदाहरण:

curl -X PATCH "https://chastify.net/api/extensions/sessions/$SESSION_ID/state" \
-H "Authorization: Bearer $DEVELOPER_KEY" \
-H "x-chastify-main-token: $MAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"counter": 2
}
}'

state.get

यह क्या करता है:

  • वर्तमान एक्सटेंशन स्थिति को पढ़ता है।
  • आईफ्रेम ब्रिज के माध्यम से उपलब्ध है।

कब उपयोग करें:

  • आईफ्रेम लोड होने पर।
  • लिखने के बाद, यदि आप स्थानीय UI को पुनः सिंक्रनाइज़ करना चाहते हैं।

उदाहरण:

{
"action": "state.get",
"payload": {}
}

फ़ाइल संग्रहण

पहेली छवियों, जेनरेट किए गए पूर्वावलोकन या चुनौती फ़ोटो जैसे बाइनरी मीडिया के लिए files.* का उपयोग करें। लौटाए गए file.id को बैकएंड-लिखित स्थिति या अपने स्वयं के डेटाबेस में संग्रहीत करें। file.signedUrl के साथ रेंडर करें, और बाद में जब iframe लोड हो जाए तो files.get के साथ उस हस्ताक्षरित URL को रीफ़्रेश करें।

लॉक/सेशन शुरू होने से पहले चलने वाली सेटअप स्क्रीन files.upload के बजाय स्टेजेड अपलोड का उपयोग करती हैं। स्टेजेड फ़ाइलें तब तक अस्थायी रहती हैं जब तक कि एक्सटेंशन कॉन्फ़िगरेशन को provider: "chastify_storage" और fileId संदर्भ के साथ सहेजा नहीं जाता। लॉक/टेम्प्लेट सहेजने पर Chastify स्वचालित रूप से उन फ़ाइलों को क्लेम कर लेता है; इसके लिए ब्राउज़र की ओर से कोई अलग क्लेम कॉल नहीं की जाती है।

आपके बैकएंड से स्टेट/फ़ाइल विभाजन का उदाहरण:

curl -X PATCH "https://chastify.net/api/extensions/sessions/$SESSION_ID/state" \
-H "Authorization: Bearer $DEVELOPER_KEY" \
-H "x-chastify-main-token: $MAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"puzzleImageFileId": "file_record_id"
}
}'

बाद में, डिस्प्ले से पहले इमेज को रिजॉल्व करें:

const state = await bridge.request("state.get", {});
const file = await bridge.request("files.get", {
fileId: state.data.puzzleImageFileId
});
image.src = file.file.signedUrl;

files.capabilities

अपलोड नियंत्रण दिखाने से पहले इसकी जांच कर लें।

{
"action": "files.capabilities",
"payload": {}
}

रनटाइम files.upload

रनटाइम फ़ाइल अपलोड करने से एक्सटेंशन सेशन डेटा में बदलाव होता है, इसलिए यह iframe ब्रिज कमांड नहीं है। ऐप-स्कोप डेवलपर API कुंजी और x-chastify-main-token का उपयोग करके अपने बैकएंड से रनटाइम फ़ाइलें अपलोड करें।

files.get

एक स्टेबल फ़ाइल आईडी से एक हस्ताक्षरित R2 URL को रीफ़्रेश करें।

{
"action": "files.get",
"payload": {
"fileId": "file_record_id"
}
}

files.list

{
"action": "files.list",
"payload": {}
}

अपलोड की तरह ही, रनटाइम files.delete भी बैकएंड-ओनली है।

लॉक क्रियाएँ

समय जोड़ें

एंडपॉइंट: POST /api/extensions/sessions/:sessionId/action

यह क्या करता है:

  • deltaSeconds के आधार पर लॉक काउंटडाउन में समय जोड़ता या घटाता है।

कब उपयोग करें:

  • इनाम/जुर्माना बटन।
  • खेल के परिणाम (जीतने पर समय जुड़ता है, हारने पर समय घटता है)।

उदाहरण:

{
"name": "add_time",
"params": 300 // +300 sec = +5 minutes
}

क्षेत्र संबंधी टिप्पणियाँ:

  • सकारात्मक मूल्य समय बढ़ाता है।
  • नकारात्मक मान समय को हटा देता है (यदि सर्वर नियमों द्वारा अनुमति हो)।

जमाना

एंडपॉइंट: POST /api/extensions/sessions/:sessionId/action

यह क्या करता है:

  • फ्रीज़ होने पर प्रगति कुछ समय के लिए रुक जाती है।

कब उपयोग करें:

  • कूलडाउन मैकेनिज्म।
  • पुरस्कार चेकपॉइंट।

उदाहरण:

{
"name": "freeze",
"params": { "durationSeconds": 120 }
}

आप इसे durationSeconds के बिना भी कॉल कर सकते हैं:

{
"name": "freeze",
"params": {}
}

क्षेत्र संबंधी टिप्पणियाँ:

  • durationSeconds वैकल्पिक है।
  • यदि इसे छोड़ दिया जाता है, तो वर्तमान डिफ़ॉल्ट मान 3600 सेकंड (1 घंटा) है।
  • स्वीकृत सीमा 60 से 86400 सेकंड तक है।

अनफ़्रीज़

एंडपॉइंट: POST /api/extensions/sessions/:sessionId/action

यह क्या करता है:

  • सक्रिय फ्रीज़ समाप्त होता है और टाइमर का सामान्य व्यवहार फिर से शुरू होता है।

कब उपयोग करें:

  • एक्सटेंशन वर्कफ़्लो में मैन्युअल ओवरराइड।
  • “फ्रीज रद्द करें” नियंत्रण।

उदाहरण:

{
"name": "unfreeze",
"params": {}
}

निंदा करना

एंडपॉइंट: POST /api/extensions/sessions/:sessionId/action

यह क्या करता है:

  • सक्रिय लॉक सत्र के लिए दंडात्मक कार्रवाई की अवधि शुरू होती है।

कब उपयोग करें:

  • असफल कार्यों/चुनौतियों के बाद दंड की व्यवस्था।
  • ऐसे एस्केलेशन फ्लो जो लॉक के साथ बातचीत को अस्थायी रूप से प्रतिबंधित करते हैं।

उदाहरण:

{
"name": "pillory",
"params": {
"durationSeconds": 600,
"reason": "Missed scheduled check-in"
}
}

क्षेत्र संबंधी टिप्पणियाँ:

  • name को pillory होना चाहिए।
  • params.durationSeconds आवश्यक है।
  • params.reason वैकल्पिक है।
  • सेशन कॉन्फ़िगरेशन में पिलोरी को सक्षम करना आवश्यक है।

पिलोरी का अंत

एंडपॉइंट: POST /api/extensions/sessions/:sessionId/action

यह क्या करता है:

  • वर्तमान सक्रिय दंडात्मक सत्र को तुरंत समाप्त करता है।

उदाहरण:

{
"name": "pillory.end",
"params": {}
}

क्षेत्र संबंधी टिप्पणियाँ:

  • name को pillory.end होना चाहिए।
  • यदि लॉक वर्तमान में पिलोरी में नहीं है तो pillory_not_active त्रुटि के साथ विफल हो जाता है।

कार्य सौंपें

एंडपॉइंट: POST /api/extensions/sessions/:sessionId/action

यह क्या करता है:

  • एक्सटेंशन लॉजिक से पहनने वाले के लिए एक सक्रिय कार्य रन बनाता है।
  • पहले से चल रहे टास्क रन को ओवरराइड कर सकता है।

उदाहरण:

{
"name": "task.assign",
"params": {
"taskText": "Clean your room",
"points": 10,
"verificationRequired": true,
"durationSeconds": 1800
}
}

क्षेत्र संबंधी टिप्पणियाँ:

  • taskText आवश्यक है।
  • points वैकल्पिक है और सर्वर-साइड द्वारा नियंत्रित किया जाता है।
  • verificationRequired डिफ़ॉल्ट रूप से false पर सेट हो जाता है।
  • durationSeconds वैकल्पिक है (0 का अर्थ है टाइमर की कोई आवश्यकता नहीं)।
  • इसके लिए लॉक पर टास्क मॉड्यूल सक्षम होना आवश्यक है।

कार्य टाइमर प्रारंभ करें

एंडपॉइंट: POST /api/extensions/sessions/:sessionId/action

यह क्या करता है:

  • वर्तमान में सक्रिय समयबद्ध कार्य के लिए उलटी गिनती शुरू या पुनः शुरू करता है।

उदाहरण:

{
"name": "task.start_timer",
"params": {}
}

क्षेत्र संबंधी टिप्पणियाँ:

  • इसके लिए एक सक्रिय कार्य का चलना आवश्यक है।
  • यदि वर्तमान कार्य के लिए कोई अवधि निर्धारित नहीं की गई है तो यह विफल हो जाएगा।

कार्य पूरा करें

एंडपॉइंट: POST /api/extensions/sessions/:sessionId/action

यह क्या करता है:

  • सक्रिय कार्य को पूर्ण या असफल के रूप में चिह्नित करता है।

उदाहरण (सफलता):

{
"name": "task.complete",
"params": {
"successful": true
}
}

उदाहरण (असफलता):

{
"name": "task.complete",
"params": {
"successful": false,
"reason": "Did not finish in time"
}
}

अस्थायी उद्घाटन को सक्रिय करें

एंडपॉइंट: POST /api/extensions/sessions/:sessionId/action

यह क्या करता है:

  • एक्सटेंशन लॉजिक से एक अस्थायी स्वच्छता ओपनिंग विंडो शुरू करता है।

उदाहरण:

{
"name": "hygienic_unlock.start",
"params": {
"durationSeconds": 900
}
}

क्षेत्र संबंधी टिप्पणियाँ:

  • लॉक पर हाइजीनिक ओपनिंग सक्षम होना आवश्यक है।
  • यदि स्वच्छता संबंधी कोई कार्य पहले से ही चल रहा हो तो यह प्रक्रिया विफल हो जाती है।
  • durationSeconds वैकल्पिक है; इसे छोड़े जाने पर लॉक डिफ़ॉल्ट का उपयोग किया जाता है।

मेटाडेटा और होम क्रियाएँ

metadata.patch

यह क्या करता है:

  • लॉक-पेज यूआई द्वारा उपयोग किए जाने वाले एक्सटेंशन मेटाडेटा को संग्रहीत करता है।
  • unlockBlockers और homeActions को सपोर्ट करता है।
  • एक्सटेंशन खुलने पर डीप-लिंक व्यवहार के लिए homeActions[].intent का समर्थन करता है।

कब उपयोग करें:

  • अपने एक्सटेंशन के स्वामित्व वाली लॉक-सेशन अनलॉक शर्तों को लागू करें।
  • लॉक पेज पर त्वरित क्रियाएं जोड़ें जो आपके एक्सटेंशन को इंटेंट के साथ खोलें।
  • जब उपयोगकर्ता होम बटन पर क्लिक करते हैं, तो उन्हें सीधे किसी विशिष्ट स्क्रीन/वर्कफ़्लो पर ले जाया जाता है।

अंतिम बिंदु:

PATCH /api/extensions/sessions/:sessionId/metadata
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH

उदाहरण बॉडी:

{
"unlockBlockers": ["Finish extension task"],
"homeActions": [
{
"slug": "tasks",
"title": "Tasks",
"description": "Open tasks panel",
"intent": {
"type": "open_panel",
"title": "Tasks",
"message": "Open tasks panel",
"payload": {
"panel": "regular-actions"
}
}
}
]
}

क्षेत्र संबंधी टिप्पणियाँ:

  • unlockBlockers: आपके एक्सटेंशन से सक्रिय लॉक-सेशन अनलॉक ब्लॉकर की सूची।
  • आप एक साथ कई अवरोधक (अधिकतम 25) शामिल कर सकते हैं, प्रत्येक अपूर्ण स्थिति के लिए एक।
  • जब तक सक्षम एक्सटेंशनों में कोई अवरोधक मौजूद रहता है, तब तक अनलॉक अवरुद्ध रहता है।
  • Chastify लॉक सेशन के लिए सभी एक्सटेंशन से ब्लॉकर्स को एकत्रित करता है।
  • आपके एक्सटेंशन को केवल अपने मेटाडेटा में अपने स्वयं के ब्लॉकर जोड़ने/हटाने चाहिए।
  • अन्य एक्सटेंशन से ब्लॉकर न हटाएं; अपनी ऐरे को तभी साफ़ करें जब आपकी अपनी शर्तें पूरी हो जाएं।
  • homeActions: लॉक अनुभव में प्रदर्शित त्वरित क्रिया बटन।
  • homeActions[].slug: आपके एक्शन के लिए स्टेबल आईडी।
  • homeActions[].title: उपयोगकर्ता के सामने दिखने वाला लेबल।
  • homeActions[].description: वैकल्पिक सहायक पाठ।
  • homeActions[].intent: वैकल्पिक डीप-लिंक निर्देश जो आपके एक्सटेंशन को खोले जाने पर पास किया जाता है।
  • एक्सटेंशन कार्ड के यूजर इंटरफेस में, इन क्रियाओं को क्रिया शीर्षक (आंतरिक रूप से स्लग द्वारा चिह्नित) के आधार पर एक मेनू/सूची के रूप में दिखाया जाता है।
  • जब कोई उपयोगकर्ता इनमें से किसी एक पर क्लिक करता है, तो Chastify एक्सटेंशन खोलता है और निम्नलिखित जानकारी भेजता है:
    • homeActionSlug
    • homeAction (चयनित क्रिया ऑब्जेक्ट)
    • intent (सामान्यीकृत आशय वस्तु) ताकि आपका एक्सटेंशन लोड होते ही तुरंत सही व्यू/एक्शन पर रीडायरेक्ट हो सके।

इंटेंट्स: डेवलपर ऐप उदाहरण

लोड होने पर मेनू-क्लिक इंटेंट पर प्रतिक्रिया देने के लिए अपने एक्सटेंशन ऐप में इस पैटर्न का उपयोग करें।

import { useEffect, useRef } from "react";
import { parseHashPayload, type IframeHashPayload } from "../lib/ChastifyBridge";

export function useHomeActionIntent(
payload: IframeHashPayload,
routeToPanel: (panel: string) => void,
showToast: (message: string) => void,
) {
const handledRef = useRef<string>("");

useEffect(() => {
const homeActionSlug = payload?.homeActionSlug ?? null;
if (!homeActionSlug) return;

// Prevent duplicate handling if component re-renders.
const key = `${payload.lockId || "lock"}:${homeActionSlug}`;
if (handledRef.current === key) return;
handledRef.current = key;

const intent = payload?.intent ?? payload?.homeAction?.intent ?? null;
if (!intent) return;

if (intent.type === "open_panel") {
const panel = String(intent.payload?.panel || "");
if (panel) routeToPanel(panel);
return;
}

if (intent.message) {
showToast(String(intent.message));
}
}, [payload, routeToPanel, showToast]);
}

// Example app bootstrap
const payload = parseHashPayload();
if (!payload) throw new Error("Missing iframe hash payload");

यह उदाहरण क्या करता है:

  • आईफ्रेम हैश पेलोड से homeActionSlug + intent पढ़ता है।
  • यह लॉक/एक्शन स्लग के लिए प्रत्येक क्लिक को केवल एक बार ही हैंडल करता है।
  • जब intent open_panel हो तो पैनल के लिए रूट।
  • कस्टम इंटेंट प्रकारों के लिए इंटेंट संदेश दिखाने पर वापस आ जाता है।

डिवाइस कमांड

device.command

यह क्या करता है:

  • यह डिवाइस कंट्रोल कमांड भेजता है (यदि उस सेशन/डिवाइस के लिए समर्थित हो)।
  • Chastify के माध्यम से आपका एक्सटेंशन मानकीकृत शॉक/वाइब्रेशन क्रियाओं को ट्रिगर कर सकता है।

कब उपयोग करें:

  • एक्सटेंशन लॉजिक से समर्थित शॉक/वाइब्रेशन कमांड को ट्रिगर करना।
  • इंटरैक्टिव एक्सटेंशन सुविधाओं का निर्माण (गेम, दंड, पुरस्कार, दिनचर्या)।

अंतिम बिंदु:

POST /api/extensions/sessions/:sessionId/device-command
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH

उदाहरण बॉडी:

{
"command": "shock.start",
"params": {
"durationSeconds": 30,
"intensityPct": 50
}
}

सामान्य कमांड:

  • shock.start पैरामीटर के साथ: { durationSeconds, intensityPct, message? }
  • shock.stop
  • vibration.start पैरामीटर के साथ: { durationSeconds, intensityPct, frequencyPct?, message? }
  • vibration.stop
  • all.stop
  • shock.random.set पैरामीटर के साथ: { enabled, minIntensityPct?, maxIntensityPct?, message? } (केवल Lockink AA-A1012)
  • shock.berserk.set पैरामीटर के साथ: { enabled, message? } (केवल Lockink AA-A1012)

अनुशंसित प्रवाह:

  1. लोड होने पर session.get को कॉल करें।
  2. deviceControl.supportedCommands से डिवाइस की क्षमताओं को पढ़ें।
  3. केवल समर्थित कमांड के लिए ही नियंत्रण प्रदर्शित करें।
  4. मान्य मानों के साथ device.command भेजें।
  5. लाइव यूआई स्थिति के लिए रिफ्रेश करें या प्रतिक्रिया active फ़्लैग पर भरोसा करें।

पैरामीटर मार्गदर्शन:

  • durationSeconds: सर्वर सुरक्षित सीमाओं तक सीमित है (वर्तमान नीति की अधिकतम सीमा 300 सेकंड है)।
  • intensityPct: अपेक्षित प्रतिशत मान (1-100 शैली इनपुट, सर्वर-साइड पर सीमित)।
  • frequencyPct: कंपन प्रवाह (क्लैम्प्ड सर्वर-साइड) के लिए अपेक्षित प्रतिशत मान (1-100)।
  • रैंडम मोड के लिए, सुनिश्चित करें कि minIntensityPct <= maxIntensityPct हो।

सुरक्षित यूआई पैटर्न का उदाहरण:

// 1) Get capabilities first
const session = await bridge.request("session.get", {});
const supported = new Set(session?.deviceControl?.supportedCommands ?? []);

// 2) Only call command if supported
if (supported.has("shock.start")) {
await bridge.request("device.command", {
command: "shock.start",
params: { durationSeconds: 30, intensityPct: 50 }
});
}

महत्वपूर्ण:

  • पहले session.get को कॉल करें और समर्थित कमांड पढ़ें।
  • केवल उन्हीं कमांड के लिए नियंत्रण दिखाएं जो वर्तमान सत्र में समर्थित हैं।
  • कमांड पैरामीटर भेजने से पहले उपयोगकर्ता द्वारा दिए गए इनपुट को सत्यापित करें।
  • device.command को एक्सटेंशन सत्र के लिए लेखन अनुमति (locks:write) की आवश्यकता है।
  • ब्रिज/सर्वर त्रुटियों को सुचारू रूप से संभालें (insufficient_scope, असमर्थित कमांड, सत्यापन त्रुटियां)।

विस्तार आवश्यकताएँ

एक्सटेंशन की आवश्यकताओं के तहत एक एक्सटेंशन आवर्ती पूर्णता नियमों को परिभाषित कर सकता है जो लॉक के टुडे प्रोग्रेस यूआई में दिखाई देते हैं और पहनने वाले द्वारा समय सीमा चूक जाने पर दंड लागू कर सकते हैं।

इसका उपयोग सर्वर-विश्वसनीय एक्सटेंशन गतिविधियों के लिए करें, जैसे कि:

  • प्रतिदिन एक पहेली पूरी करें।
  • हर 2 दिन में 3 बार चेक-इन करें।
  • प्रति सप्ताह 5 अतिरिक्त कार्य पूरे करें।

विन्यास आकार

यह आवश्यकता एक्सटेंशन सेशन कॉन्फ़िगरेशन में extensionRequirements के अंतर्गत संग्रहीत है:

{
"extensionRequirements": {
"enabled": true,
"metric": "completion",
"requiredCount": 1,
"cadence": {
"every": 1,
"unit": "day"
},
"punishment": {
"type": "add_time",
"seconds": 900,
"reason": "Missed extension requirement"
}
}
}

क्षेत्र:

  • enabled: आवर्ती आवश्यकता को चालू/बंद करता है।
  • metric: स्टेबल काउंटर का नाम। सरल नामों जैसे completion, win, या verification का उपयोग करें।
  • requiredCount: विंडो में कितने विश्वसनीय इवेंट होने चाहिए।
  • cadence.every: अंतराल का आकार।
  • cadence.unit: day या week.
  • विंडो का टाइमज़ोन उपयोगकर्ता के कॉन्फ़िगर किए गए User.timezone से Chastify द्वारा निर्धारित किया जाता है। एक्सटेंशन कॉन्फ़िगरेशन में टाइमज़ोन को हार्डकोड नहीं किया जाना चाहिए।
  • punishment.type: none, add_time, freeze, या pillory.
  • punishment.seconds: add_time, freeze, या pillory के लिए दंड की अवधि।
  • punishment.reason: वैकल्पिक ऑडिट/डीबग कारण।

प्रगति मॉडल

आवश्यकता की प्रगति विश्वसनीय सर्वर-साइड स्थिति है, न कि आईफ्रेम-स्थानीय स्थिति।

आवश्यकता को पूर्ण के रूप में चिह्नित करने के लिए state.patch / state.put का उपयोग न करें। ये क्रियाएँ केवल बैकएंड-आधारित सामान्य स्थिति लेखन हैं, न कि आवश्यकता प्रगति API। आवश्यकता प्रगति को तभी रिकॉर्ड किया जाना चाहिए जब सर्वर उस घटना को मान्य कर ले जिसे गिना जाना चाहिए।

उदाहरण के लिए:

  • एक पहेली एक्सटेंशन को सर्वर द्वारा हस्ताक्षरित पहेली रन और पूर्ण स्थिति को मान्य करने के बाद ही प्रगति को रिकॉर्ड करना चाहिए।
  • एक सत्यापन एक्सटेंशन को सर्वर द्वारा प्रस्तुत प्रमाण को स्वीकार करने के बाद ही प्रगति को रिकॉर्ड करना चाहिए।
  • गेम एक्सटेंशन को प्रगति तभी रिकॉर्ड करनी चाहिए जब बैकएंड गेम के परिणाम या विश्वसनीय समापन इवेंट को मान्य कर ले।

रनटाइम व्यवहार

कॉन्फ़िगरेशन होने पर:

  • लॉक डैशबोर्ड आज की प्रगति में आवश्यकता को दिखा सकता है।
  • Chastify प्रत्येक एक्सटेंशन सत्र और प्रत्येक कैडेंस विंडो के अनुसार प्रगति को ट्रैक करता है।
  • निर्धारित आवश्यकता कार्य पूर्ण किए गए विंडो का मूल्यांकन करता है और प्रत्येक छूटे हुए विंडो के लिए एक बार निर्धारित दंड लागू करता है।
  • दंड प्रत्येक विंडो के लिए समान होते हैं, इसलिए पुनः प्रयास करने पर दोहरा दंड नहीं लगता है।
  1. एक्सटेंशन सेटअप/कॉन्फ़िगरेशन UI में extensionRequirements को कॉन्फ़िगर करें।
  2. रनटाइम स्टार्टअप पर, session.get को कॉल करें और सक्रिय कॉन्फ़िगरेशन पढ़ें।
  3. यूआई में एक्सटेंशन गतिविधि को पूरा करें।
  4. उस एक्सटेंशन के लिए किसी विश्वसनीय बैकएंड रूट पर पूर्णता भेजें।
  5. बैकएंड को इवेंट को मान्य करने दें और आवश्यकता की प्रगति को रिकॉर्ड करने दें।
  6. कार्य पूरा होने के बाद session.get / state.get का उपयोग करके स्थानीय UI को रीफ़्रेश करें।

महत्वपूर्ण:

  • state.* को केवल एक्सटेंशन के स्वामित्व वाले स्टोरेज के रूप में ही मानें। प्रगति, प्रयासों, पुरस्कारों और दंडों के लिए समर्पित विश्वसनीय API का उपयोग करें।
  • आवश्यकताओं के लिए केवल क्लाइंट-आधारित पूर्णता फ़्लैग पर भरोसा न करें।
  • metric नामों को स्थिर रखें; मीट्रिक बदलने से गिनती एक अलग श्रेणी में शुरू हो जाती है।
  • Chastify कैडेंस विंडो के लिए पहनने वाले के कॉन्फ़िगर किए गए टाइमज़ोन का उपयोग करता है। यदि उपयोगकर्ता पर कोई टाइमज़ोन उपलब्ध नहीं है, तो सर्वर UTC पर वापस आ जाता है।
  • ऑडिट लॉग में दंडों को सीमित और स्पष्ट रखें।
  1. स्टार्टअप पर session.get को कॉल करें।
  2. state.get के साथ स्थिति पढ़ें।
  3. आवश्यकता पड़ने पर PUT/PATCH /state का उपयोग करके अपने बैकएंड से स्टेट राइट्स करें।
  4. लॉक/डिवाइस संबंधी कार्रवाइयां केवल तभी चलाएं जब वे समर्थित हों और यूजर इंटरफेस में दिखाई दें।
  5. आवश्यकता-आधारित गतिविधियों के लिए, पूर्णता की रिपोर्ट एक विश्वसनीय बैकएंड रूट को भेजें।
  6. महत्वपूर्ण लेखन/कार्यों के बाद स्थानीय दृश्य को रीफ़्रेश करें।