API-eksempler
Bruk denne siden til å kopiere riktig forespørselsform for hver utvidelsesflyt.
- Eksempler på iframe-broer bruker
postMessage-handlinger somsession.get,state.getogfiles.get. - Privilegerte eksempler bruker din egen utvidelsesbackend med
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEYogx-chastify-main-token. - Send aldri en Developer API-nøkkel til iframe eller nettleserkode.
Iframe-broen er for UI-oppstart og lavrisiko-øktoperasjoner. Bruk den til å lese kontekst, lagre utvidelseseid tilstand og løse fil-URL-er.
Nettleserens iframe-kode er brukerstyrt. Ikke bruk iframe-broforespørsler til å bruke/fjerne tid, fullføre oppgaver, fjerne opplåsingsblokkeringer, laste opp/slette kjøretidsfiler, sende varsler, skrive logger eller kommandere enheter.
Forespørsels- og svarformat
Sikre iframe-brohandlinger sendes i denne broforespørselskonvolutten:
{
"type": "chastify:ext:req", // required
"v": 1, // protocol version
"id": "req-123", // your unique request id
"nonce": "from-iframe-hash",
"action": "session.get",
"payload": {}
}
Og du mottar:
{
"type": "chastify:ext:resp",
"v": 1,
"id": "req-123", // same id you sent
"ok": true,
"data": {}
}
Hvis ok er false, kryss av for error.code og error.message.
Eksempler som kun brukes i backend-format bruker vanlige HTTPS-forespørsler fra serveren din. De sendes ikke via iframe-broen.
Økt og kontekst
session.get
Bruk dette først i nesten alle utvidelsesflyter.
Hva den gjør:
- Bekrefter at broforbindelsen din fungerer.
- Returnerer øktkontekst (låsestatus, rolle, utvidelseskonfigurasjon, funksjoner).
- Returnerer informasjon om enhetsfunksjonalitet som brukergrensesnittet ditt kan bruke før det ber backend-enheten om å kalle
device.command.
Hva det brukes til:
- Bootstrapping av brukergrensesnittet ditt.
- Aktivering/deaktivering av funksjoner basert på rolle og tillatelser.
- Kontrollerer støttede enhetskommandoer før gjengivelse av enhetskontroller.
Eksempel på handlingsnyttelast:
{
"action": "session.get",
"payload": {}
}
Eksempel på session.get-svarutdrag (låsedata for kjøretid):
{
"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
}
}
}
Personvernmerknader:
wearerLastSeenTimestamp/keyholderLastSeenTimestampreturneres bare hvis brukeren harshowOnlineStatus !== false.- Hvis synlighet av onlinestatus er deaktivert, er disse feltene
null.
Flyter for backend-utvidelser
Disse eksemplene viser det sikre produksjonsmønsteret:
- Iframe-en leser
mainTokenogsessionIdfra hash-nyttelasten. - Iframe-en sender dem til backend-en din.
- Backend-en din validerer din egen spill-/oppgave-/forretningstilstand.
- Backend-en din kaller Chastify med en app-scoped Developer API-nøkkel pluss
x-chastify-main-token.
Ikke bruk sessionId alene som autentisering. Behandle mainToken som en oppstartskontekst som er synlig i nettleseren, og behandle Developer API-nøkkelen din som en hemmelighet kun for backend.
Backend-en din må validere sin egen spill-/oppgavestatus før den kaller Chastify. Å sende mainToken og sessionId fra iframe-en identifiserer bare den åpnede utvidelsesøkten; det beviser ikke at brukeren fullførte en utfordring.
Hent øktkontekst på en sikker måte
Iframen din kan bruke den sikre broen session.get for UI-oppstart. Hvis backend-en din trenger samme kontekst før en privilegert handling kan brukes, må du hente den fra backend-en din med begge påloggingsinformasjonene.
Iframe:
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
})
});
Bakenden din:
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
});
});
Bruk tid fra en utvidelsesbackend
Nettleseren kan be backend-serveren din om å bruke en belønning eller straff, men nettleseren må ikke avgjøre om handlingen er gyldig. Bekreft handlingen på serversiden først.
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());
});
Bruk add_time for straffer og remove_time for belønninger.
Serververifisert spillfullføring
For spill som Simon Says, ikke stol på en klientrapportert gevinst. Opprett kjøringen på serversiden, lagre den forventede sekvensen eller en hash av den, og bekreft den innsendte inputen før du kaller Chastify.
Et nettlesersynlig minnespill kan ikke bevise at et menneske har spilt ærlig, fordi nettleseren må motta sekvensen for å gjengi spillet. Serververifisering forhindrer fortsatt forfalskede Chastify-mutasjoner og lar backend-en din håndheve løps-ID-er, utløp, vanskelighetsgrad, kadens, poengsum og replay-beskyttelse før belønninger eller straffer iverksettes.
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 });
});
Det nøyaktige lagringsskjemaet for kjører er ditt. verifySessionLaunch bør kalle Chastify med din app-scoped Developer API-nøkkel og x-chastify-main-token før sessionId stoles på. Den viktige regelen er at Chastify-mutasjoner bare skjer etter at backend-en din har bekreftet oppstarten og resultatet.
Planlagte krav
Backend-systemet ditt eier tidsplaner, kadenskontroller og bevisvalidering. Bruk Chastify kun til å registrere pålitelig fremdrift eller oppdatere opplåsingsblokkeringer etter at backend-systemet ditt har bestemt at kravet er oppfylt.
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
})
});
}
Nåværende API-er for installerte utvidelsesøkter krever et gyldig iframe-oppstartstoken i x-chastify-main-token. Oppstartstokener utløper for øyeblikket etter 10 timer. For planlagte jobber som kjører etter at tokenet utløper, lagrer du ditt eget ventende bevis og sender inn fremdriften ved neste gyldige utvidelsesoppstart, eller bruker en førsteparts-/innebygd serverflyt designet for uovervåket bakgrunnsarbeid.
Ikke behandle planlagte jobber som klarerte bare fordi de kjører på serveren din. Jobben trenger fortsatt bevis på serversiden, kadenskontroller, avspillingsbeskyttelse og en gyldig Chastify-autorisasjonssti før kravfremdriften registreres.
Varsler
notifications.custom
Bruk dette fra utvidelsens backend for å sende et tilpasset utvidelsesvarsel til bruker, nøkkelinnehaver eller begge deler.
Endepunkt:
POST /api/extensions/sessions/:sessionId/notifications/custom
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH
Eksempel på brødtekst:
{
"title": "Extension Reminder",
"message": "Your next challenge is ready.",
"showPageOverlay": false,
"target": "both"
}
Merknader:
showPageOverlayhar standardverdienfalse.targethar standardverdienwearer.- API-et oppretter varslingstypen
extension_app_message.
Utvidelsesstatus
Utvidelsesstatus er dine utvidelseseide JSON-data for den gjeldende låseøkten.
Tilstandsskrivinger er kun for backend og krever en app-scoped Developer API-nøkkel pluss økten mainToken. Iframes kan lese tilstand med state.get, men de kan ikke skrive tilstand direkte.
state.put
Hva den gjør:
- Erstatter hele tilstandsobjektet med det nye
data-objektet. - Krever backend-legitimasjon.
Når du skal bruke:
- Første lagring.
- Full overskriving når du allerede har den komplette nye tilstanden.
Eksempel:
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"
}
}'
Feltnotater:
payload.data: en hvilken som helst gyldig JSON-verdi/-objekt som utvidelsen din trenger.- Avoid Mongo-unsafe key names (
$prefix or keys containing.). - Tilstanden er øktbegrenset og størrelsesbegrenset av utvidelsesappens
stateMaxBytes, med standardinnstilling på 64 KiB. - Lagre fil-ID-er i tilstand, ikke binære filer eller signerte URL-er. Bruk
files.getfor å oppdatere signerte URL-er før gjengivelse av media.
state.patch
Hva den gjør:
- Bruker en JSON-flettingsoppdatering på eksisterende tilstand.
- Bare endrede nøkler må sendes.
- Krever backend-legitimasjon.
Når du skal bruke:
- Trinnvise oppdateringer fra brukerinteraksjoner.
- Oppdaterer ett felt uten å sende alt på nytt.
Eksempel:
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
Hva den gjør:
- Leser gjeldende status for utvidelsen.
- Tilgjengelig via iframe-broen.
Når du skal bruke:
- Ved innlasting av iframe.
- Etter skrivinger, hvis du vil synkronisere det lokale brukergrensesnittet på nytt.
Eksempel:
{
"action": "state.get",
"payload": {}
}
Fillagring
Bruk files.* for binære medier som puslespillbilder, genererte forhåndsvisninger eller utfordringsbilder. Lagre den returnerte file.id i backend-skrevet tilstand eller i din egen database. Gjengi med file.signedUrl, og oppdater den signerte URL-en med files.get når iframe-en lastes inn senere.
Oppsettskjermer som kjører før en lås/økt eksisterer, bruker trinnvise opplastinger i stedet for files.upload. Trinnvise filer er midlertidige inntil utvidelseskonfigurasjonen lagres med en provider: "chastify_storage"- og fileId-referanse. Chastify krever disse filene automatisk ved låsing/mallagring; det er ikke noe separat kravkall på nettlesersiden.
Eksempel på delt tilstand/fil fra backend-systemet ditt:
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"
}
}'
Senere, løs opp bildet før visning:
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
Sjekk dette før du viser opplastingskontroller.
{
"action": "files.capabilities",
"payload": {}
}
Kjøretid files.upload
Opplasting av kjøretidsfiler muterer utvidelsesøktsdata, så det er ikke en iframe-brokommando. Last opp kjøretidsfiler fra backend-en din med en app-scoped Developer API-nøkkel og x-chastify-main-token.
files.get
Oppdater én signert R2-URL fra en stabil fil-ID.
{
"action": "files.get",
"payload": {
"fileId": "file_record_id"
}
}
files.list
{
"action": "files.list",
"payload": {}
}
Kjøretidsprogrammet files.delete er også kun for backend av samme grunn som opplasting.
Låshandlinger
Legg til tid
Endepunkt: POST /api/extensions/sessions/:sessionId/action
Hva den gjør:
- Legger til eller fjerner tid fra nedtellingen til låsen, avhengig av
deltaSeconds.
Når du skal bruke:
- Belønnings-/straffeknapper.
- Kamputfall (seier legger til tid, tap fjerner tid).
Eksempel:
{
"name": "add_time",
"params": 300 // +300 sec = +5 minutes
}
Feltnotater:
- Positiv verdi tilfører tid.
- Negativ verdi fjerner tid (hvis tillatt av serverreglene).
Fryse
Endepunkt: POST /api/extensions/sessions/:sessionId/action
Hva den gjør:
- Fryser låseprogresjonen i en viss periode.
Når du skal bruke:
- Nedkjølingsmekanikk.
- Belønningssjekkpunkter.
Eksempel:
{
"name": "freeze",
"params": { "durationSeconds": 120 }
}
Du kan også kalle det uten durationSeconds:
{
"name": "freeze",
"params": {}
}
Feltnotater:
durationSecondser valgfritt.- Hvis utelatt, er gjeldende standard
3600sekunder (1 time). - Akseptert område er
60til86400sekunder.
Tin opp
Endepunkt: POST /api/extensions/sessions/:sessionId/action
Hva den gjør:
- Avslutter aktiv frysing og gjenopptar normal timeroppførsel.
Når du skal bruke:
- Manuell overstyring i arbeidsflyter for utvidelser.
- «Avbryt frysing»-kontroller.
Eksempel:
{
"name": "unfreeze",
"params": {}
}
Gapestokk
Endepunkt: POST /api/extensions/sessions/:sessionId/action
Hva den gjør:
- Starter en gapestokkperiode for den aktive låseøkten.
Når du skal bruke:
- Straffemekanismer etter mislykkede oppgaver/utfordringer.
- Eskaleringsflyter som midlertidig begrenser låsesamhandling.
Eksempel:
{
"name": "pillory",
"params": {
"durationSeconds": 600,
"reason": "Missed scheduled check-in"
}
}
Feltnotater:
namemå værepillory.params.durationSecondser obligatorisk.params.reasoner valgfritt.- Krever at gapestokken er aktivert i øktkonfigurasjonen.
Endegapestokk
Endepunkt: POST /api/extensions/sessions/:sessionId/action
Hva den gjør:
- Avslutter den gjeldende aktive gapestokkøkten umiddelbart.
Eksempel:
{
"name": "pillory.end",
"params": {}
}
Feltnotater:
namemå værepillory.end.- Mislykkes med
pillory_not_activehvis låsen ikke er i gapestokken for øyeblikket.
Tildel oppgave
Endepunkt: POST /api/extensions/sessions/:sessionId/action
Hva den gjør:
- Oppretter en aktiv oppgavekjøring for brukeren fra utvidelseslogikk.
- Kan overstyre en allerede åpen oppgavekjøring.
Eksempel:
{
"name": "task.assign",
"params": {
"taskText": "Clean your room",
"points": 10,
"verificationRequired": true,
"durationSeconds": 1800
}
}
Feltnotater:
taskTexter obligatorisk.pointser valgfri og begrenset på serversiden.verificationRequiredhar standardverdienfalse.durationSecondser valgfritt (0betyr at det ikke er behov for timer).- Krever at Oppgaver-modulen er aktivert på låsen.
Start oppgavetimeren
Endepunkt: POST /api/extensions/sessions/:sessionId/action
Hva den gjør:
- Starter eller starter nedtellingsvinduet på nytt for den aktive tidsbestemte oppgaven.
Eksempel:
{
"name": "task.start_timer",
"params": {}
}
Feltnotater:
- Krever en aktiv oppgavekjøring.
- Mislykkes hvis den gjeldende oppgaven ikke har konfigurert varighet.
Fullfør oppgaven
Endepunkt: POST /api/extensions/sessions/:sessionId/action
Hva den gjør:
- Markerer den aktive oppgaven som fullført eller mislykket.
Eksempel (suksess):
{
"name": "task.complete",
"params": {
"successful": true
}
}
Eksempel (feil):
{
"name": "task.complete",
"params": {
"successful": false,
"reason": "Did not finish in time"
}
}
Utløs midlertidig åpning
Endepunkt: POST /api/extensions/sessions/:sessionId/action
Hva den gjør:
- Starter et midlertidig åpningsvindu for hygiene fra utvidelseslogikk.
Eksempel:
{
"name": "hygienic_unlock.start",
"params": {
"durationSeconds": 900
}
}
Feltnotater:
- Krever at hygienisk åpning er aktivert på låsen.
- Mislykkes hvis en hygieneåpning allerede pågår.
durationSecondser valgfritt; standardlås brukes når det utelates.
Metadata og startsidehandlinger
metadata.patch
Hva den gjør:
- Lagrer utvidelsesmetadata som brukes av brukergrensesnittet for låste sider.
- Støtter
unlockBlockersoghomeActions. - Støtter
homeActions[].intentfor dyplenke-atferd når utvidelsen åpnes.
Når du skal bruke:
- Håndhev opplåsingsbetingelser for låseøkter som eies av utvidelsen din.
- Legg til hurtighandlinger på låsesiden som åpner utvidelsen din med vilje.
- Send brukere direkte til en bestemt skjerm/arbeidsflyt når de klikker på en startsidehandling.
Endepunkt:
PATCH /api/extensions/sessions/:sessionId/metadata
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH
Eksempel på brødtekst:
{
"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"
}
}
}
]
}
Feltnotater:
unlockBlockers: liste over aktive blokkeringer for opplåsing av låseøkter fra utvidelsen din.- Du kan inkludere flere blokkeringer samtidig (opptil 25), én per udekket betingelse.
- Opplåsing forblir blokkert så lenge det finnes en blokkering på tvers av aktiverte utvidelser.
- Chastify samler blokkeringer fra alle utvidelser for låseøkten.
- Utvidelsen din skal bare legge til/fjerne sine egne blokkeringer i sine egne metadata.
- Ikke fjern blokkeringer fra andre utvidelser; fjern bare arrayet ditt når dine egne betingelser er oppfylt.
homeActions: hurtigknapper vises i låseopplevelsen.homeActions[].slug: stabil ID for handlingen din.homeActions[].title: brukerrettet etikett.homeActions[].description: valgfri hjelpetekst.homeActions[].intent: valgfri dyplenkeinstruksjon sendt til utvidelsen din når den åpnes.- I brukergrensesnittet på utvidelseskortet vises disse handlingene som en meny/liste etter handlingstittel (internt tastet inn av slug).
- Når en bruker klikker på en, åpner Chastify utvidelsen og sender:
homeActionSlughomeAction(valgt handlingsobjekt)intent(normalisert intensjonsobjekt) slik at utvidelsen din umiddelbart kan rute til riktig visning/handling ved innlasting.
Intents: eksempel på utviklerapp
Bruk dette mønsteret i utvidelsesappen din for å reagere på menyklikk-intensjoner ved lasting.
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");
Hva dette eksemplet gjør:
- Leser
homeActionSlug+intentfra iframe-hash-nyttelasten. - Håndterer hvert klikk bare én gang per lås-/handlingsslug.
- Ruter til et panel når intensjonen er
open_panel. - Går tilbake til å vise en intensjonsmelding for tilpassede intensjonstyper.
Enhetskommando
device.command
Hva den gjør:
- Sender en enhetskontrollkommando (hvis støttes for den økten/enheten).
- Lar forlengelsesenheten utløse standardiserte støt-/vibrasjonshandlinger gjennom Chastify.
Når du skal bruke:
- Utløser støttede støt-/vibrasjonskommandoer fra utvidelseslogikk.
- Bygge interaktive utvidelsesfunksjoner (spill, straffer, belønninger, rutiner).
Endepunkt:
POST /api/extensions/sessions/:sessionId/device-command
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH
Eksempel på brødtekst:
{
"command": "shock.start",
"params": {
"durationSeconds": 30,
"intensityPct": 50
}
}
Vanlige kommandoer:
shock.startmed parameterne:{ durationSeconds, intensityPct, message? }shock.stopvibration.startmed parameterne:{ durationSeconds, intensityPct, frequencyPct?, message? }vibration.stopall.stopshock.random.setmed parameterne:{ enabled, minIntensityPct?, maxIntensityPct?, message? }(kun Lockink AA-A1012)shock.berserk.setmed parameterne:{ enabled, message? }(kun Lockink AA-A1012)
Anbefalt strømning:
- Kall
session.getved lasting. - Les enhetsfunksjoner fra
deviceControl.supportedCommands. - Gjengi kun kontroller for støttede kommandoer.
- Send
device.commandmed validerte verdier. - Oppdater eller stol på svaret
active-flagg for status for live UI.
Parameterveiledning:
durationSeconds: serveren holder seg innenfor sikre grenser (gjeldende maks. for regelen er 300 sekunder).intensityPct: forventet prosentverdi (1-100-stilinndata, begrenset på serversiden).frequencyPct: forventet prosentverdi (1-100) for vibrasjonsflyter (fastklemt på serversiden).- For tilfeldig modus, sørg for
minIntensityPct <= maxIntensityPct.
Eksempel på et sikrere brukergrensesnittmønster:
// 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 }
});
}
Viktig:
- Kall
session.getførst og les støttede kommandoer. - Vis bare kontroller for kommandoer som støttes i gjeldende økt.
- Valider brukerinndata før du sender kommandoparametere.
device.commandkrever skrivetillatelse (locks:write) for utvidelsesøkten.- Håndter bro-/serverfeil på en elegant måte (
insufficient_scope, kommando som ikke støttes, valideringsfeil).
Krav til utvidelse
Utvidelseskrav lar en utvidelse definere regelmessige fullføringsregler som vises i låsens brukergrensesnitt for fremdrift i dag, og kan ilegge en straff når brukeren går glipp av et vindu.
Bruk dette for serverklarerte utvidelsesaktiviteter som:
- Fullfør 1 puslespill per dag.
- Fullfør 3 innsjekkinger annenhver dag.
- Fullfør 5 utvidelseshandlinger per uke.
Konfigurasjonsform
Kravet er lagret i konfigurasjonen for utvidelsesøkten under extensionRequirements:
{
"extensionRequirements": {
"enabled": true,
"metric": "completion",
"requiredCount": 1,
"cadence": {
"every": 1,
"unit": "day"
},
"punishment": {
"type": "add_time",
"seconds": 900,
"reason": "Missed extension requirement"
}
}
}
Felt:
enabled: slår det gjentakende kravet av/på.metric: Stabilt tellernavn. Bruk enkle navn somcompletion,winellerverification.requiredCount: hvor mange klarerte hendelser som må skje i vinduet.cadence.every: intervallstørrelse.cadence.unit:dayellerweek.- Vindustidssonen løses av Chastify fra brukerens konfigurerte
User.timezone. Utvidelseskonfigurasjonen skal ikke hardkode en tidssone. punishment.type:none,add_time,freezeellerpillory.punishment.seconds: straffevarighet foradd_time,freezeellerpillory.punishment.reason: valgfri revisjons-/feilsøkingsårsak.
Fremdriftsmodell
Kravfremdriften er klarert serversidetilstand, ikke iframe-lokal tilstand.
Ikke bruk state.patch / state.put for å markere et krav som fullført. Disse handlingene er generelle tilstandsskrivinger kun for backend, ikke API-er for kravfremdrift. Kravfremdrift må bare registreres etter at serveren validerer hendelsen som skal telle.
For eksempel:
- En puslespillutvidelse skal bare registrere fremgang etter at serveren validerer den signerte puslespillkjøringen og fullført tilstand.
- En bekreftelsesutvidelse skal bare registrere fremdrift etter at serveren har godtatt det innsendte beviset.
- En spillutvidelse skal bare registrere fremgang etter at backend-systemet validerer spillresultatet eller den pålitelige fullføringshendelsen.
Kjøretidsoppførsel
Når konfigurert:
- Låsedashbordet kan vise kravet i Dagens fremdrift.
- Chastify sporer fremgang per forlengelsesøkt og per kadensvindu.
- Den planlagte kravjobben evaluerer fullførte vinduer og bruker den konfigurerte straffen én gang per tapt vindu.
- Straffer er idempotente per vindu, så nye forsøk stabler ikke dupliserte straffer.
Anbefalt kravflyt
- Konfigurer
extensionRequirementsi brukergrensesnittet for oppsett/konfigurasjon av utvidelsen. - Ved oppstart under kjøring, kall
session.getog les den aktive konfigurasjonen. - Fullfør utvidelsesaktiviteten i brukergrensesnittet.
- Send fullføringen til en klarert backend-rute for den utvidelsen.
- La backend-systemet validere fremdriften for hendelsen og registreringskravet.
- Oppdater det lokale brukergrensesnittet med
session.get/state.getetter at det er fullført.
Viktig:
- Behandle
state.*kun som utvidelseseid lagring. Bruk dedikerte, pålitelige API-er for fremgang, forsøk, belønninger og straffer. - Ikke stol på klientens fullføringsflagg for krav.
- Hold
metric-navnene stabile; endring av metrikken begynner å telle i en annen kategori. - Chastify bruker brukerens konfigurerte tidssone for kadensvinduer. Hvis ingen tidssone er tilgjengelig for brukeren, går serveren tilbake til
UTC. - Hold straffer begrenset og forklarlige i revisjonslogger.
Anbefalt handlingsrekkefølge
- Kall
session.getved oppstart. - Lesestatus med
state.get. - Utfør tilstandsskrivinger fra backend-en din med
PUT/PATCH /statenår det er nødvendig. - Kjør lås-/enhetshandlinger bare når det støttes og er synlig i brukergrensesnittet.
- For kravbaserte aktiviteter, rapporter fullføring til en pålitelig backend-rute.
- Oppdater den lokale visningen etter viktige skrivinger/handlinger.