git.fiddlerwoaroof.com
Raw Blame History
addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

function parse_url(url) {
  const theURL = url instanceof URL ? url : new URL(url);
  return [theURL.pathname.split("/"), theURL.searchParams];
}

function uuidv4() {
  return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
    (
      c ^
      (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
    ).toString(16),
  );
}

function ok(body, init) {
  return new Response(body, { ...init, status: 200 });
}

function handlePath(path, searchParams) {
  const uuid = path.length >= 2 && path[1];
  const response = path.length === 4 && path[3];
  if (response) {
    return { route: "respond", uuid, response, email: path[2] };
  } else if (uuid) {
    return { route: "summary", uuid };
  } else {
    return { route: "notfound", path, searchParams };
  }
}

async function get() {}

const routeHandlers = {
  async notfound({ path }) {
    return new Response(`invalid path ${path}`, { status: 404 });
  },
  async summary({ uuid }) {
    const settings = await RSVPS.get(`${uuid}:settings`);

    if (settings) {
      const rsvps = {};
      let args = { prefix: `${uuid}:response:` };
      let rawRSVPs;
      do {
        rawRSVPs = await RSVPS.list(args);
        for (let { name } of rawRSVPs.keys) {
          const [_, __, email] = name.split(":");
          const response = await RSVPS.get(name);
          rsvps[email] = response;
        }
        args = { cursor: rawRSVPs.cursor };
      } while (!rawRSVPs.list_complete);
      const responseData = {
        settings: JSON.parse(settings),
        rsvps,
      };
      return ok(JSON.stringify(responseData), {
        headers: { "Content-Type": "application/json" },
      });
    } else {
      return new Response(`invalid invite ${uuid}`, { status: 404 });
    }
  },

  async respond({ uuid, email, response }) {
    const settings = await RSVPS.get(`${uuid}:settings`);
    if (settings) {
      if (!email.includes("@")) {
        return new Response(`invalid email ${response}`, { status: 404 });
      }
      if (response === "yes" || response === "no" || response === "maybe") {
        await RSVPS.put(`${uuid}:response:${email}`, response);
        return new Response(`${uuid} ${email} ${response}`, { status: 200 });
      } else {
        return new Response(`invalid response ${response}`, { status: 404 });
      }
    } else {
      return new Response(`invalid invite ${uuid}`, { status: 404 });
    }
  },
};

const methodHandlers = {
  async GET(p, sp) {
    const route = handlePath(p, sp);
    return await routeHandlers[route.route](route);
  },
  async POST() {
    const inviteUUID = uuidv4();
    await RSVPS.put(`${inviteUUID}:settings`, "{}");
    return ok(inviteUUID);
  },
  default() {
    return new Response("405 unsupported", { status: 405 });
  },
};

/**
 * Respond with hello worker text
 * @param {Request} request
 */
async function handleRequest(request) {
  /** @type {number} */
  const nums = JSON.parse((await RSVPS.get("test:count")) || "0") + 1;
  await RSVPS.put("test:count", JSON.stringify(nums));
  const [p, sp] = parse_url(request.url);

  return await (methodHandlers[request.method] || methodHandlers.default)(
    p,
    sp,
  );
}