-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathxword-fetcher.js
executable file
·94 lines (78 loc) · 2.95 KB
/
xword-fetcher.js
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import puppeteer from 'puppeteer';
import fs from 'fs';
import wrap from 'wordwrap';
const nytMiniURL='https://www.nytimes.com/crosswords/game/mini';
const boardPath = 'xwd_board.png';
const puzzleTextPath = 'puzzle.txt';
// DOM selectors - subject to changes on NYT xword page
const modalBtnSelector = 'button[aria-label="OK"]';
const xwdBoardSelector = '#xwd-board';
const puzzleDateSelector = '[class^="PuzzleDetails-date"]';
const clueNumSelector = 'span[class^="Clue-label"]';
const clueSelector = 'span[class^="Clue-text"]';
const acrossTitle = '\nACROSS\r\n';
const downTitle = '\nDOWN\r\n';
(async () => {
try {
console.log('* Navigating to NYT Mini Crossword page...\n');
// debug
// const browser = await puppeteer.launch({ headless: false, slowMo: 100, defaultViewport: null });
// use chromium-browser for rpi3
const browser = await puppeteer.launch({ executablePath: 'chromium-browser', defaultViewport: null });
const [page] = await browser.pages();
await page.setViewport({ width: 800, height:1000 });
// Wait until no more than 2 active connections open
await page.goto(nytMiniURL, { waitUntil: 'networkidle2' });
console.log('* Page loaded');
await page.waitForSelector(modalBtnSelector, { visible: true });
await page.click(modalBtnSelector);
console.log('* Modal button clicked');
// Retrieve xword board
const xwdBoardElem = await page.$(xwdBoardSelector);
const xwdBoardBoundingBox = await xwdBoardElem.boundingBox();
console.log('* Board loaded')
await xwdBoardElem.screenshot({
path: boardPath,
clip: {
x: xwdBoardBoundingBox.x,
y: xwdBoardBoundingBox.y,
width: Math.min(xwdBoardBoundingBox.width, page.viewport().width),
height: 390,
},
});
console.log(`* Board screenshot saved to ${boardPath}`)
// Retrieve puzzle date
const puzzleDateElem = await page.$$eval(puzzleDateSelector,
elem => elem.map( c => c.textContent )
)
const puzzleDate = puzzleDateElem[0];
console.log(`* Puzzle date found: ${puzzleDate}`)
// Retrieve clues
const clueNums = await page.$$eval(clueNumSelector,
elem => elem.map( c => c.textContent )
)
const clues = await page.$$eval(clueSelector,
elem => elem.map( c => c.textContent )
)
console.log('* Clues found')
// Format and write date/clues to file
let puzzleText = `${puzzleDate}\n${acrossTitle}`;
let clueColumn = 0;
let wrappedClue = '';
for (let i = 0; i < clues.length; i++) {
if (clueNums[i] == 1) clueColumn++;
if (clueColumn == 2) {
puzzleText += downTitle;
clueColumn = 0;
}
wrappedClue = wrap(32)(`${clueNums[i]} ${clues[i]}`)
puzzleText += `${wrappedClue}\n`;
}
fs.writeFileSync(puzzleTextPath, puzzleText);
console.log(`* Puzzle text saved to ${puzzleTextPath}\n`);
console.log(puzzleText);
browser.close();
} catch (err) {
console.error(err);
}
})();