Primjeri API-ja
Pomoću ove stranice kopirajte odgovarajući oblik zahtjeva za svaki tijek proširenja.
- Primjeri iframe mostova koriste
postMessageakcije kao što susession.get,state.getifiles.get. - Privilegirani primjeri koriste vlastito proširenje sa
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEYix-chastify-main-token. - Nikada ne šaljite ključ API-ja razvojnog programera u iframe ili kod preglednika.
iframe most je za UI bootstrap i operacije sesije niskog rizika. Koristite ga za čitanje konteksta, pohranjivanje stanja u vlasništvu ekstenzije i razrješavanje URL-ova datoteka.
iframe kod preglednika kontrolira korisnik. Nemojte koristiti iframe bridge zahtjeve za primjenu/uklanjanje vremena, dovršavanje zadataka, brisanje blokatora otključavanja, prijenos/brisanje datoteka za vrijeme izvođenja, slanje obavijesti, pisanje zapisnika ili naređivanje uređaja.
Format zahtjeva i odgovora
Sigurne iframe akcije mosta šalju se unutar ove omotnice zahtjeva za most:
{
"type": "chastify:ext:req", // required
"v": 1, // protocol version
"id": "req-123", // your unique request id
"nonce": "from-iframe-hash",
"action": "session.get",
"payload": {}
}
I primate:
{
"type": "chastify:ext:resp",
"v": 1,
"id": "req-123", // same id you sent
"ok": true,
"data": {}
}
Ako je ok jednak false, provjerite error.code i error.message.
Primjeri samo za pozadinsku konfiguraciju koriste normalne HTTPS zahtjeve s vašeg poslužitelja. Ne šalju se putem iframe mosta.
Sesija i kontekst
session.get
Koristite ovo prvo u gotovo svakom tijeku proširenja.
Što radi:
- Potvrđuje da vaša mostna veza radi.
- Vraća kontekst sesije (stanje zaključavanja, uloga, konfiguracija proširenja, mogućnosti).
- Vraća informacije o mogućnostima uređaja koje vaše korisničko sučelje može koristiti prije nego što zatraži od pozadinskog sustava da pozove
device.command.
Za što se koristi:
- Pokretanje vašeg korisničkog sučelja.
- Omogućavanje/onemogućavanje značajki na temelju uloge i dopuštenja.
- Provjera podržanih naredbi uređaja prije renderiranja kontrola uređaja.
Primjer akcijskog sadržaja:
{
"action": "session.get",
"payload": {}
}
Primjer izvatka odgovora session.get (podaci o zaključavanju za vrijeme izvođenja):
{
"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
}
}
}
Napomene o privatnosti:
wearerLastSeenTimestamp/keyholderLastSeenTimestampse vraćaju samo ako taj korisnik imashowOnlineStatus !== false.- Ako je vidljivost online statusa onemogućena, ova polja su
null.
Tokovi pozadinskog proširenja
Ovi primjeri pokazuju obrazac sigurne proizvodnje:
- iframe čita
mainTokenisessionIdiz hash sadržaja. - iframe ih šalje vašem backendu.
- Vaš backend potvrđuje stanje vaše igre/zadatka/posla.
- Vaš backend poziva Chastify s ključem API-ja razvojnog programera u opsegu aplikacije plus
x-chastify-main-token.
Ne koristite sessionId samo za autentifikaciju. Tretirajte mainToken kao kontekst pokretanja vidljiv pregledniku, a svoj ključ API-ja za razvojne programere tretirajte kao tajnu samo za pozadinu.
Vaš backend mora provjeriti vlastito stanje igre/zadatka prije pozivanja Chastify. Prosljeđivanje mainToken i sessionId iz iframea samo identificira otvorenu sesiju proširenja; ne dokazuje da je korisnik dovršio izazov.
Sigurno dohvaćanje konteksta sesije
Vaš iframe može koristiti sigurni most session.get za UI bootstrap. Ako vašem backendu treba isti kontekst prije primjene privilegirane akcije, dohvatite ga iz backenda s obje vjerodajnice.
Unutarnji okvir:
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
})
});
Vaš pozadinski sustav:
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
});
});
Primijeni vrijeme iz pozadinskog sustava proširenja
Preglednik može zatražiti od vašeg pozadinskog sustava da primijeni nagradu ili kaznu, ali preglednik ne smije odlučiti je li radnja valjana. Prvo provjerite radnju na strani poslužitelja.
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());
});
Za kazne koristite add_time, a za nagrade remove_time.
Završetak igre potvrđen od strane poslužitelja
Za igre poput Simon Says, nemojte vjerovati pobjedi koju prijavi klijent. Kreirajte izvršavanje na strani poslužitelja, pohranite očekivani slijed ili njegov hash i provjerite poslani unos prije pozivanja Chastify.
Igra memorije vidljiva pregledniku ne može dokazati da je čovjek igrao pošteno, jer preglednik mora primiti sekvencu za renderiranje igre. Verifikacija poslužitelja i dalje sprječava krivotvorene mutacije Chastify i omogućuje vašem backendu da primijeni ID-ove pokretanja, istek, težinu, ritam, bodovanje i zaštitu od ponovnog igranja prije primjene nagrada ili kazni.
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 });
});
Točna shema pohrane pokretanja je vaša. verifySessionLaunch treba pozvati Chastify s vašim ključem API-ja razvojnog programera u opsegu aplikacije i x-chastify-main-token prije nego što povjeri sessionId. Važno pravilo je da se mutacije Chastify događaju tek nakon što vaš backend potvrdi pokretanje i rezultat.
Planirani zahtjevi
Vaš backend posjeduje rasporede, provjere ritma i validaciju dokaza. Koristite Chastify samo za bilježenje pouzdanog napretka ili ažuriranje blokatora otključavanja nakon što vaš backend odluči da je zahtjev ispunjen.
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
})
});
}
Trenutni API-ji sesija instaliranih proširenja zahtijevaju valjani token za pokretanje iframea u x-chastify-main-token; tokeni za pokretanje trenutno istječu nakon 10 sati. Za zakazane zadatke koji se pokreću nakon isteka tog tokena, pohranite vlastiti dokaz na čekanju i pošaljite napredak pri sljedećem valjanom pokretanju proširenja ili upotrijebite tok poslužitelja prve strane/ugrađenog poslužitelja dizajniran za rad u pozadini bez nadzora.
Nemojte tretirati zakazane zadatke kao pouzdane samo zato što se izvode na vašem poslužitelju. Zadatak i dalje zahtijeva provjeru na strani poslužitelja, provjeru ritma, zaštitu od ponavljanja i valjanu Chastify autorizacijsku putanju prije snimanja napretka zahtjeva.
Obavijesti
notifications.custom
Upotrijebite ovo iz pozadinskog sustava vašeg proširenja za slanje prilagođene obavijesti o proširenju korisniku, vlasniku ključa ili oboma.
Krajnja točka:
POST /api/extensions/sessions/:sessionId/notifications/custom
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH
Primjer tijela:
{
"title": "Extension Reminder",
"message": "Your next challenge is ready.",
"showPageOverlay": false,
"target": "both"
}
Bilješke:
showPageOverlayje zadanofalse.targetje zadanowearer.- API stvara obavijest tipa
extension_app_message.
Stanje proširenja
Stanje ekstenzije su JSON podaci u vlasništvu vaše ekstenzije za trenutnu sesiju zaključavanja.
Zapisivanje stanja je samo u pozadini i zahtijeva ključ API-ja razvojnog programera na razini aplikacije plus sesiju mainToken. IFrameovi mogu čitati stanje s state.get, ali ne mogu izravno zapisivati stanje.
state.put
Što radi:
- Zamjenjuje cijeli objekt stanja novim objektom
data. - Zahtijeva pozadinske vjerodajnice.
Kada koristiti:
- Početno spremanje.
- Potpuno prepisivanje kada već imate potpuno novo stanje.
Primjer:
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"
}
}'
Bilješke s terena:
payload.data: bilo koja valjana JSON vrijednost/objekt koji je potreban vašem proširenju.- Avoid Mongo-unsafe key names (
$prefix or keys containing.). - Stanje je ograničeno na razini sesije i veličinu prema
stateMaxBytesaplikacije proširenja, a zadana vrijednost je 64 KiB. - Pohrani ID-ove datoteka u stanju, a ne binarne datoteke ili potpisane URL-ove. Koristite
files.getza osvježavanje potpisanih URL-ova prije prikazivanja medija.
state.patch
Što radi:
- Primjenjuje JSON zakrpu za spajanje na postojeće stanje.
- Potrebno je poslati samo promijenjene ključeve.
- Zahtijeva pozadinske vjerodajnice.
Kada koristiti:
- Inkrementalna ažuriranja iz interakcija korisnika.
- Ažuriranje jednog polja bez ponovnog slanja svega.
Primjer:
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
Što radi:
- Čita trenutno stanje ekstenzije.
- Dostupno putem iframe mosta.
Kada koristiti:
- Pri učitavanju iframea.
- Nakon pisanja, ako želite ponovno sinkronizirati lokalno korisničko sučelje.
Primjer:
{
"action": "state.get",
"payload": {}
}
Pohrana datoteka
Koristite files.* za binarne medije kao što su slike zagonetki, generirani pregledi ili fotografije izazova. Pohranite vraćeni file.id u stanju napisanom u pozadini ili u vlastitu bazu podataka. Renderirajte s file.signedUrl i osvježite taj potpisani URL s files.get kada se iframe kasnije učita.
Zasloni za postavljanje koji se pokreću prije nego što postoji zaključavanje/sesija koriste postupne prijenose umjesto files.upload. Postupne datoteke su privremene dok se konfiguracija proširenja ne spremi s referencom provider: "chastify_storage" i fileId. Chastify automatski preuzima te datoteke prilikom spremanja zaključavanja/predloška; ne postoji zaseban poziv za preuzimanje na strani preglednika.
Primjer podjele stanja/datoteke s vašeg backenda:
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"
}
}'
Kasnije, razriješite sliku prije prikaza:
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
Provjerite ovo prije prikazivanja kontrola prijenosa.
{
"action": "files.capabilities",
"payload": {}
}
Vrijeme izvođenja files.upload
Prijenos datoteka za vrijeme izvođenja mutira podatke sesije proširenja, tako da nije naredba za iframe most. Prenesite datoteke za vrijeme izvođenja sa svog backenda pomoću ključa API-ja razvojnih programera s opsegom aplikacije i x-chastify-main-token.
files.get
Osvježi jedan potpisani R2 URL iz stabilnog ID-a datoteke.
{
"action": "files.get",
"payload": {
"fileId": "file_record_id"
}
}
files.list
{
"action": "files.list",
"payload": {}
}
Runtime files.delete je također samo za pozadinsku upotrebu iz istog razloga kao i upload.
Zaključaj radnje
Dodaj vrijeme
Krajnja točka: POST /api/extensions/sessions/:sessionId/action
Što radi:
- Dodaje ili uklanja vrijeme iz odbrojavanja brave ovisno o
deltaSeconds.
Kada koristiti:
- Gumbi za nagradu/kaznu.
- Ishodi igre (pobjeda dodaje vrijeme, poraz oduzima vrijeme).
Primjer:
{
"name": "add_time",
"params": 300 // +300 sec = +5 minutes
}
Bilješke s terena:
- Pozitivna vrijednost dodaje vrijeme.
- Negativna vrijednost uklanja vrijeme (ako je dopušteno pravilima poslužitelja).
Zamrznuti
Krajnja točka: POST /api/extensions/sessions/:sessionId/action
Što radi:
- Zamrzava napredak na određeno vrijeme.
Kada koristiti:
- Mehanika hlađenja.
- Nagradne kontrolne točke.
Primjer:
{
"name": "freeze",
"params": { "durationSeconds": 120 }
}
Možete ga pozvati i bez durationSeconds:
{
"name": "freeze",
"params": {}
}
Bilješke s terena:
durationSecondsje opcionalan.- Ako se izostavi, trenutna zadana vrijednost je
3600sekundi (1 sat). - Prihvaćeni raspon je od
60do86400sekundi.
Odmrzni
Krajnja točka: POST /api/extensions/sessions/:sessionId/action
Što radi:
- Završava aktivno zamrzavanje i nastavlja normalno ponašanje timera.
Kada koristiti:
- Ručno poništavanje u tijekovima rada proširenja.
- Kontrole za "Otkaži zamrzavanje".
Primjer:
{
"name": "unfreeze",
"params": {}
}
Strijelac srama
Krajnja točka: POST /api/extensions/sessions/:sessionId/action
Što radi:
- Pokreće razdoblje srama za aktivnu sesiju zaključavanja.
Kada koristiti:
- Mehanika kažnjavanja nakon neuspjelih zadataka/izazova.
- Tokovi eskalacije koji privremeno ograničavaju interakciju brava.
Primjer:
{
"name": "pillory",
"params": {
"durationSeconds": 600,
"reason": "Missed scheduled check-in"
}
}
Bilješke s terena:
namemora bitipillory.- Potreban je
params.durationSeconds. params.reasonje opcionalan.- Zahtijeva da stub srama bude omogućen u konfiguraciji sesije.
Kraj srama
Krajnja točka: POST /api/extensions/sessions/:sessionId/action
Što radi:
- Odmah završava trenutnu aktivnu sesiju srama.
Primjer:
{
"name": "pillory.end",
"params": {}
}
Bilješke s terena:
namemora bitipillory.end.- Ne uspijeva s
pillory_not_activeako brava trenutno nije na stubu srama.
Dodijeli zadatak
Krajnja točka: POST /api/extensions/sessions/:sessionId/action
Što radi:
- Stvara aktivno izvršavanje zadatka za korisnika iz logike proširenja.
- Može nadjačati već otvoreno izvršavanje zadatka.
Primjer:
{
"name": "task.assign",
"params": {
"taskText": "Clean your room",
"points": 10,
"verificationRequired": true,
"durationSeconds": 1800
}
}
Bilješke s terena:
- Potreban je
taskText. pointsje opcionalan i ograničen na strani poslužitelja.verificationRequiredje zadanofalse.durationSecondsje opcionalan (0znači da nema potrebe za timerom).- Zahtijeva omogućen modul Zadaci na bravi.
Pokreni mjerač vremena zadatka
Krajnja točka: POST /api/extensions/sessions/:sessionId/action
Što radi:
- Pokreće ili ponovno pokreće prozor odbrojavanja za trenutno aktivni vremenski zadatak.
Primjer:
{
"name": "task.start_timer",
"params": {}
}
Bilješke s terena:
- Zahtijeva aktivno izvršavanje zadatka.
- Ne uspijeva ako trenutni zadatak nema konfigurirano trajanje.
Dovrši zadatak
Krajnja točka: POST /api/extensions/sessions/:sessionId/action
Što radi:
- Označava aktivno izvršavanje zadatka kao dovršeno ili neuspješno.
Primjer (uspjeh):
{
"name": "task.complete",
"params": {
"successful": true
}
}
Primjer (neuspjeh):
{
"name": "task.complete",
"params": {
"successful": false,
"reason": "Did not finish in time"
}
}
Pokreni privremeno otvaranje
Krajnja točka: POST /api/extensions/sessions/:sessionId/action
Što radi:
- Pokreće privremeni prozor za otvaranje higijenskih podataka iz logike proširenja.
Primjer:
{
"name": "hygienic_unlock.start",
"params": {
"durationSeconds": 900
}
}
Bilješke s terena:
- Zahtijeva omogućeno higijensko otvaranje na bravi.
- Ne uspijeva ako je higijensko otvaranje već u tijeku.
durationSecondsje opcionalan; kada se izostavi, koristi se zadana vrijednost zaključavanja.
Metapodaci i početne radnje
metadata.patch
Što radi:
- Pohranjuje metapodatke proširenja koje koristi korisničko sučelje zaključane stranice.
- Podržava
unlockBlockersihomeActions. - Podržava
homeActions[].intentza ponašanje dubokih poveznica prilikom otvaranja proširenja.
Kada koristiti:
- Provedite uvjete otključavanja sesije zaključavanja u vlasništvu vašeg proširenja.
- Dodajte brze radnje na zaključanoj stranici koje otvaraju vaše proširenje s namjerom.
- Usmjerite korisnike izravno na određeni zaslon/tijek rada kada kliknu na početnu radnju.
Krajnja točka:
PATCH /api/extensions/sessions/:sessionId/metadata
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH
Primjer tijela:
{
"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"
}
}
}
]
}
Bilješke s terena:
unlockBlockers: popis aktivnih blokatora otključavanja sesije zaključavanja s vaše ekstenzije.- Možete uključiti više blokatora odjednom (do 25), jedan po neispunjenom uvjetu.
- Otključavanje ostaje blokirano dok god postoji bilo koji blokator na omogućenim proširenjima.
- Chastify agregira blokatore iz svih ekstenzija za sesiju zaključavanja.
- Vaše proširenje treba dodavati/uklanjati vlastite blokatore samo u vlastitim metapodacima.
- Ne briši blokatore iz drugih ekstenzija; briši svoj niz samo kada su zadovoljeni tvoji vlastiti uvjeti.
homeActions: tipke za brzu akciju prikazane su u iskustvu zaključavanja.homeActions[].slug: stabilan ID za vašu akciju.homeActions[].title: oznaka okrenuta prema korisniku.homeActions[].description: opcionalni pomoćni tekst.homeActions[].intent: opcionalna instrukcija za duboku vezu prosljeđuje se vašem proširenju prilikom otvaranja.- U korisničkom sučelju kartice za proširenje, ove se radnje prikazuju kao izbornik/popis prema naslovu radnje (interno se unosi pomoću slug-a).
- Kada korisnik klikne na jedan, Chastify otvara ekstenziju i prosljeđuje:
homeActionSlughomeAction(odabrani objekt akcije)intent(normalizirani objekt namjere) tako da vaše proširenje može odmah usmjeriti na ispravan prikaz/radnju prilikom učitavanja.
Namjere: primjer aplikacije za razvojne programere
Koristite ovaj uzorak u svojoj aplikaciji za proširenje kako biste reagirali na namjere klika na izbornik prilikom učitavanja.
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");
Što ovaj primjer radi:
- Čita
homeActionSlug+intentiz korisnog tereta iframe hash-a. - Obrađuje svaki klik samo jednom po zaključavanju/akciji.
- Usmjerava na panel kada je namjera
open_panel. - Vraća se na prikazivanje poruke o namjeri za prilagođene vrste namjere.
Naredba uređaja
device.command
Što radi:
- Šalje naredbu za upravljanje uređajem (ako je podržana za tu sesiju/uređaj).
- Omogućuje vašem proširenju da pokrene standardizirane radnje udara/vibracije putem Chastify.
Kada koristiti:
- Pokretanje podržanih naredbi za udarce/vibracije iz logike proširenja.
- Izgradnja interaktivnih značajki proširenja (igre, kazne, nagrade, rutine).
Krajnja točka:
POST /api/extensions/sessions/:sessionId/device-command
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH
Primjer tijela:
{
"command": "shock.start",
"params": {
"durationSeconds": 30,
"intensityPct": 50
}
}
Uobičajene naredbe:
shock.starts parametrima:{ durationSeconds, intensityPct, message? }shock.stopvibration.starts parametrima:{ durationSeconds, intensityPct, frequencyPct?, message? }vibration.stopall.stopshock.random.sets parametrima:{ enabled, minIntensityPct?, maxIntensityPct?, message? }(samo Lockink AA-A1012)shock.berserk.sets parametrima:{ enabled, message? }(samo Lockink AA-A1012)
Preporučeni protok:
- Pozovite
session.getpri učitavanju. - Pročitajte mogućnosti uređaja iz
deviceControl.supportedCommands. - Renderiraj samo kontrole za podržane naredbe.
- Pošalji
device.commands provjerenim vrijednostima. - Zastavice za osvježavanje ili pouzdanje odgovora
activeza stanje korisničkog sučelja uživo.
Smjernice za parametre:
durationSeconds: poslužitelj se ograničava na sigurne granice (trenutni maksimum pravila je 300s).intensityPct: očekivana postotna vrijednost (unos u stilu1-100, ograničeno na strani poslužitelja).frequencyPct: očekivana postotna vrijednost (1-100) za vibracijske tokove (zaključano na strani poslužitelja).- Za nasumični način rada, osigurajte
minIntensityPct <= maxIntensityPct.
Primjer uzorka sigurnijeg korisničkog sučelja:
// 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 }
});
}
Važno:
- Prvo pozovite
session.geti pročitajte podržane naredbe. - Prikaži samo kontrole za naredbe koje su podržane u trenutnoj sesiji.
- Validirajte korisničke unose prije slanja parametara naredbe.
device.commandzahtijeva dozvolu za pisanje (locks:write) za sesiju proširenja.- Graciozno obradi pogreške mosta/poslužitelja (
insufficient_scope, nepodržana naredba, pogreške validacije).
Zahtjevi za proširenje
Zahtjevi za proširenje omogućuju proširenju da definira pravila ponavljajućeg dovršavanja koja se prikazuju u korisničkom sučelju brave Today Progress i mogu primijeniti kaznu kada nositelj propusti prozor.
Koristite ovo za aktivnosti proširenja kojima poslužitelj vjeruje, kao što su:
- Riješite 1 zagonetku dnevno.
- Obavite 3 prijave svaka 2 dana.
- Izvršite 5 radnji proširenja tjedno.
Oblik konfiguracije
Zahtjev je pohranjen u konfiguraciji sesije proširenja pod extensionRequirements:
{
"extensionRequirements": {
"enabled": true,
"metric": "completion",
"requiredCount": 1,
"cadence": {
"every": 1,
"unit": "day"
},
"punishment": {
"type": "add_time",
"seconds": 900,
"reason": "Missed extension requirement"
}
}
}
Polja:
enabled: uključuje/isključuje ponavljajući zahtjev.metric: stabilan naziv brojača. Koristite jednostavne nazive kao što sucompletion,winiliverification.requiredCount: koliko se pouzdanih događaja mora dogoditi u prozoru.cadence.every: veličina intervala.cadence.unit:dayiliweek.- Vremensku zonu prozora određuje Chastify iz konfiguriranog
User.timezonekorisnika. Konfiguracija ekstenzije ne smije fiksno kodirati vremensku zonu. punishment.type:none,add_time,freezeilipillory.punishment.seconds: trajanje kazne zaadd_time,freezeilipillory.punishment.reason: neobavezni razlog revizije/otklanjanja pogrešaka.
Model napretka
Napredak zahtjeva je pouzdano stanje na strani poslužitelja, a ne stanje iframe-lokalno.
Nemojte koristiti state.patch / state.put za označavanje zahtjeva kao dovršenog. Te radnje su zapisi općeg stanja samo za pozadinsku komponentu, a ne API-ji za napredak zahtjeva. Napredak zahtjeva mora se zabilježiti tek nakon što poslužitelj potvrdi događaj koji bi se trebao računati.
Na primjer:
- Proširenje slagalice trebalo bi bilježiti napredak tek nakon što poslužitelj potvrdi potpisano izvršavanje slagalice i stanje završetka.
- Proširenje za provjeru trebalo bi bilježiti napredak tek nakon što poslužitelj prihvati poslani dokaz.
- Proširenje igre trebalo bi bilježiti napredak tek nakon što pozadinski sustav potvrdi rezultat igre ili pouzdani događaj završetka.
Ponašanje tijekom izvođenja
Kada je konfigurirano:
- Nadzorna ploča zaključavanja može prikazati zahtjev u Današnjem napretku.
- Chastify prati napredak po sesiji ekstenzije i po prozoru kadence.
- Planirani zadatak zahtjeva procjenjuje dovršene prozore i primjenjuje konfiguriranu kaznu jednom za svaki propušteni prozor.
- Kazne su idempotentne po prozoru, tako da ponovni pokušaji ne zbrajaju duplicirane kazne.
Preporučeni tok zahtjeva
- Konfigurirajte
extensionRequirementsu korisničkom sučelju za postavljanje/konfiguraciju proširenja. - Prilikom pokretanja, pozovite
session.geti pročitajte aktivnu konfiguraciju. - Dovršite aktivnost proširenja u korisničkom sučelju.
- Pošaljite dovršetak na pouzdanu pozadinsku rutu za to proširenje.
- Neka pozadinski sustav potvrdi događaj i zabilježi napredak zahtjeva.
- Osvježite lokalno korisničko sučelje s
session.get/state.getnakon završetka.
Važno:
- Tretirajte
state.*samo kao pohranu u vlasništvu ekstenzije. Koristite namjenske pouzdane API-je za napredak, pokušaje, nagrade i kazne. - Ne vjerujte zastavicama dovršetka samo za klijenta za zahtjeve.
- Održavajte stabilnim imena
metric; promjena metrike počinje brojati u drugu kategoriju. - Chastify koristi konfiguriranu vremensku zonu korisnika za prozore kadence. Ako vremenska zona nije dostupna na korisniku, poslužitelj se vraća na
UTC. - Kazne neka budu ograničene i objašnjive u zapisnicima revizije.
Preporučeni redoslijed radnji
- Pozovite
session.getpri pokretanju. - Pročitajte stanje sa
state.get. - Izvršite zapisivanje stanja iz vašeg backenda pomoću
PUT/PATCH /statekada je potrebno. - Pokreni radnje zaključavanja/uređaja samo kada su podržane i vidljive u korisničkom sučelju.
- Za aktivnosti podržane zahtjevima, prijavite dovršetak pouzdanoj pozadinskoj ruti.
- Osvježi lokalni prikaz nakon važnih zapisa/radnji.