Skip to content

Commit

Permalink
added server source code
Browse files Browse the repository at this point in the history
  • Loading branch information
shahata committed Oct 25, 2024
1 parent c80107e commit 0b93d97
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/server/deno.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import worker from './worker.js';

Deno.serve(worker.fetch);

Check failure on line 3 in src/server/deno.js

View workflow job for this annotation

GitHub Actions / test

'Deno' is not defined
10 changes: 10 additions & 0 deletions src/server/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"deploy": {
"project": "652c6edb-dacd-440a-845e-8ea175eddd31",
"exclude": [
"**/node_modules"
],
"include": [],
"entrypoint": "deno.js"
}
}
3 changes: 3 additions & 0 deletions src/server/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash
deployctl deploy --prod
npx wrangler deploy
95 changes: 95 additions & 0 deletions src/server/worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
function cleanError(s) {
return s.match(/<h1>(.*)<\/h1>/)?.[1] || s;
}

function cleanAnswer(s) {
return s.match(/<article><p>([^.]*\.)/)?.[1] || s;
}

function cleanQuestion(s) {
return s.match(/(?<=<p>Your puzzle answer was <code>).*?(?=<\/code>)/g) || [];
}

async function downloadContent(url, session, postPayload) {
const headers = { Cookie: `session=${session}` };
const options = { headers };
if (postPayload) {
Object.assign(options, {
body: postPayload,
method: 'POST',
});
Object.assign(options.headers, {
'content-type': 'application/x-www-form-urlencoded',
});
}
const response = await fetch(url, options);
if (response.status >= 400) {
throw new Error(
[
`Failed to download from ${url} (${response.status})`,
`Description: ${cleanError(await response.text())}`,
].join('\n'),
);
}
return await response.text();
}

async function getDayAnswer(year, day, session) {
const url = `https://adventofcode.com/${+year}/day/${+day}`;
return cleanQuestion(await downloadContent(url, session));
}

async function getDayInput(year, day, session) {
const url = `https://adventofcode.com/${+year}/day/${+day}/input`;
return await downloadContent(url, session);
}

async function submitDayAnswer(year, day, session, level, answer) {
const url = `https://adventofcode.com/${+year}/day/${+day}/answer`;
const postPayload = `level=${level}&answer=${encodeURIComponent(answer)}`;
return cleanAnswer(await downloadContent(url, session, postPayload));
}

async function respond(fn) {
try {
const body = await fn();
return new Response(
typeof body === 'string' ? body : JSON.stringify(body),
{
status: 200,
headers: { 'Access-Control-Allow-Origin': '*' },
},
);
} catch (e) {
return new Response(e.toString(), {
status: 500,
headers: { 'Access-Control-Allow-Origin': '*' },
});
}
}

export default {
async fetch(req) {
let match;
const session = new URL(req.url).searchParams.get('session');
match = new URLPattern({ pathname: '/input/:year/:day' }).exec(req.url);

Check failure on line 75 in src/server/worker.js

View workflow job for this annotation

GitHub Actions / test

'URLPattern' is not defined
if (req.method === 'GET' && match) {
const { year, day } = match.pathname.groups;
return respond(() => getDayInput(year, day, session));
}
match = new URLPattern({ pathname: '/question/:year/:day' }).exec(req.url);

Check failure on line 80 in src/server/worker.js

View workflow job for this annotation

GitHub Actions / test

'URLPattern' is not defined
if (req.method === 'GET' && match) {
const { year, day } = match.pathname.groups;
return respond(() => getDayAnswer(year, day, session));
}
match = new URLPattern({ pathname: '/answer/:year/:day' }).exec(req.url);

Check failure on line 85 in src/server/worker.js

View workflow job for this annotation

GitHub Actions / test

'URLPattern' is not defined
if (req.method === 'POST' && match) {
const { year, day } = match.pathname.groups;
const formData = await req.formData();
const level = formData.get('level');
const answer = formData.get('answer');
return respond(() => submitDayAnswer(year, day, session, level, answer));
}
return new Response('Not found', { status: 404 });
},
};
8 changes: 8 additions & 0 deletions src/server/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#:schema node_modules/wrangler/config-schema.json
name = "aoc"
main = "worker.js"
compatibility_date = "2024-10-22"
compatibility_flags = ["nodejs_compat"]

[observability]
enabled = true
1 change: 1 addition & 0 deletions src/utils/urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ export const imports = {
};

// export const aocSolverServer = 'https://www.wix.com/_serverless/adventofcode';
// export const aocSolverServer = 'https://aoc.shahar-talmi.workers.dev';
export const aocSolverServer = 'https://aoc.deno.dev';

0 comments on commit 0b93d97

Please sign in to comment.