I am using a Cloudflare worker to make a website that lets you run Luau code, here is the full worker.js
const main_page = `
<!DOCTYPE html>
<html>
<head>
<title>Execute Luau</title>
</head>
<body>
<form action="/new-task" method="POST" target="logs">
<input type="text" name="api-key" placeholder="API key"/>
<br/>
<input type="number" name="place-id" placeholder="Place ID"/>
<br/>
<input type="number" name="timeout" placeholder="Script timeout (in seconds)"/>
<br/>
<textarea name="script"></textarea>
<br/>
<button type="submit">Run</button>
</form>
<iframe name="logs" style="width:100%; height:300px;"></iframe>
</body>
</html>
`;
async function getUniverseId(placeId) {
return (await (await fetch(`https://apis.roblox.com/universes/v1/places/${placeId}/universe`)).json()).universeId;
};
async function fetchCloudV2Api(apiKey, path, body = null, method = "GET") {
return (await fetch("https://apis.roblox.com/cloud/v2/" + path, {
headers: {
"Content-Type": "application/json",
"x-api-key": apiKey,
},
body,
method,
})).json();
};
async function newTask(apiKey, placeId, body) {
const universeId = await getUniverseId(placeId);
return fetchCloudV2Api(
apiKey,
`/universes/${universeId}/places/${placeId}/luau-execution-session-tasks`,
JSON.stringify(body),
"POST"
);
};
async function awaitTaskCompletion(apiKey, task) {
const path = task.path + "?view=BASIC";
const requestsPerMinute = 45;
const intervalMs = (60 / requestsPerMinute) * 1000;
return new Promise(function (resolve, reject) {
async function poll() {
const task = await fetchCloudV2Api(apiKey, path);
switch (task.state) {
case "PROCESSING": {
setTimeout(poll, intervalMs);
break;
};
case "FAILED": {
reject(task.error.message);
return;
};
case "COMPLETE": {
resolve(task);
return;
};
default: {
throw new Error("Unknown state: " + task.state);
}
}
};
poll();
});
}
async function getTaskLogs(apiKey, task) {
const path = task.path + "/logs?view=STRUCTURED&maxPageSize=10000";
const requestsPerMinute = 45;
const intervalMs = (60 / requestsPerMinute) * 1000;
const result = [];
let nextPageToken = "";
return new Promise(function(resolve) {
async function fetchNext() {
const page = await fetchCloudV2Api(apiKey, path + "&pageToken=" + encodeURIComponent(nextPageToken));
for (const taskLog of page.luauExecutionSessionTaskLogs) {
result.push(...taskLog.structuredMessages);
};
nextPageToken = page.nextPageToken;
if (!nextPageToken) {
resolve(result);
return;
};
setTimeout(fetchNext, intervalMs);
};
fetchNext();
})
}
export default {
async fetch(request) {
try {
const requestUrl = new URL(request.url);
// const searchParams = Object.fromEntries(requestUrl.searchParams.entries());
const pathname = requestUrl.pathname.replace(/\/$/, '');
if (!pathname) {
return new Response(main_page, {
headers: {
"Content-Type": "text/html"
},
status: 200,
});
} else if (pathname === "/new-task") {
const formData = await request.formData();
const apiKey = formData.get("api-key");
const placeId = formData.get("place-id");
const script = formData.get("script");
const timeout = formData.get("timeout");
if (!apiKey) {
return new Response("Missing 'api-key' in FormData", {
status: 400
});
};
if (!placeId) {
return new Response("Missing 'place-id' in FormData", {
status: 400
})
};
const task = await newTask(apiKey, placeId, {
script,
timeout: timeout + "s",
});
await awaitTaskCompletion(apiKey, task);
return new Response(JSON.stringify(await getTaskLogs(apiKey, task)), {
headers: {
"Content-Type": "application/json",
}
});
}
return new Response("Unknown page", {
status: 404
});
} catch (error) {
return new Response(error, {
status: 500
});
}
}
}
When I input my API Key PlaceID, all that stuff sometimes it works, but sometimes it says this:
{'errors':[{'code':9009,'message':'WAF Blocked Request'}]}
This is erroring because of await newTask(...)
Please help
Thanks