forked from T-Hugs/advent-of-code
-
Notifications
You must be signed in to change notification settings - Fork 1
/
login.ts
77 lines (72 loc) · 3.19 KB
/
login.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import inquirer from "inquirer";
import playwright from "playwright-chromium";
import { log, SolutionObject, solutionLogKey } from "./util/log";
import chalk from "chalk";
import { LocalStorage } from "node-localstorage";
import path from "path";
import { getAppRoot } from "./util/util";
const appRoot = getAppRoot();
const localStorage = new LocalStorage(path.join(appRoot, ".scratch"));
const providers = ["GitHub", "Google", "Twitter", "Reddit"] as const;
async function getTokenInteractive(provider: string) {
const browser = await playwright.chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
await page.goto(`https://adventofcode.com/auth/${provider.toLowerCase()}`);
await page.waitForNavigation({ url: /^https:\/\/adventofcode\.com\/$/, timeout: 0 });
const cookies = await context.cookies();
const sessionCookie = cookies.find(c => c.name === "session" && c.domain.includes("adventofcode.com"));
if (!sessionCookie) {
throw new Error("Could not acquire session cookie.");
}
browser.close();
return sessionCookie.value.trim();
}
async function run() {
log(`
Authenticate to Advent of Code to use submit and data download functions.
Note: your token will be stored in plain text in a file at ./.scratch/sessionToken.
Do not commit this file to version control! Security notice: the session token
obtained from authentication allows this framework to make requests to Advent
of Code as you! You should only continue with these steps if you trust this
software. As the author, I can only offer you a promise that it does nothing with
your credentials other than what is described in the documentation, but I
encourage you to read through the code anyway. Cheers!
`);
const mode = await inquirer.prompt([{
name: "mode",
message: "How would you like to log in?",
type: "list",
choices: ["Interactive", "Manual"]
}]);
let token: string | undefined = undefined;
if (mode.mode === "Interactive") {
const provider = await inquirer.prompt([{
name: "provider",
message: "Which auth provider would you like to use?",
type: "list",
choices: providers
}]);
token = await getTokenInteractive(provider.provider);
} else if (mode.mode === "Manual") {
log(`Follow these instructions to get your auth token and paste it in the prompt below.
1) Open https://adventofcode.com/auth/login in a web browser.
2) Open your browser's developer tools (usually F12) and switch to the network tab.
3) On the Advent of Code login page, click on the link for the auth provider of your choice.
4) Follow the steps to complete authentication. This should result in a logged-in Advent of Code page.
5) Switch back to the developer tools and look for a network request starting with "callback?" - click on it.
6) Under Response headers, find the "set-cookie" header and look for a string starting with "session=".
7) Paste everything after "session=" until the semicolon into the prompt below.
`);
token = (await inquirer.prompt([{
name: "token",
message: "Paste your session token here",
type: "input"
}])).token.trim();
}
if (token) {
localStorage.setItem("sessionToken", token);
}
log(chalk`{greenBright Done.}`);
}
run();