|
@@ -109,7 +109,7 @@ class Webshot extends CallableInstance<[Tweet[], (...args) => void, number], Pro
|
|
|
]))
|
|
|
// hide header, "more options" button, like and retweet count
|
|
|
.then(() => page.addStyleTag({
|
|
|
- content: 'header,#layers{display:none!important}article{background-color:transparent!important}' +
|
|
|
+ content: 'header,#layers,section>div>div>div~div{display:none!important}article{background-color:transparent!important}' +
|
|
|
'[data-testid="caret"],[role="group"],[data-testid="tweet"] [class*=" "]+:last-child>*+[class*=" "]~div{display:none}',
|
|
|
}))
|
|
|
.then(() => page.addStyleTag({
|
|
@@ -131,7 +131,7 @@ class Webshot extends CallableInstance<[Tweet[], (...args) => void, number], Pro
|
|
|
.then(() => page.waitForSelector(
|
|
|
'xpath=//section/*/*/div[.//article[not(.//time[not(ancestor::div[@aria-labelledby])])]]',
|
|
|
{state: 'attached', timeout: getTimeout()}
|
|
|
- ))
|
|
|
+ ) as Promise<puppeteer.ElementHandle<HTMLDivElement>>)
|
|
|
// toggle visibility of sensitive tweets
|
|
|
.then(handle => handle.$$('xpath=..//a[contains(@href,"content_you_see")]/../../..//*[@role="button"]')
|
|
|
.then(sensitiveToggles => {
|
|
@@ -159,50 +159,29 @@ class Webshot extends CallableInstance<[Tweet[], (...args) => void, number], Pro
|
|
|
})
|
|
|
.then(handle => {
|
|
|
if (handle === null) throw new puppeteer.errors.TimeoutError();
|
|
|
- return chainPromises(morePostProcessings.map(func => () => func(page, handle)));
|
|
|
+ return chainPromises(morePostProcessings.map(func => () => func(page, handle)))
|
|
|
+ .then(() => promisify(setTimeout)(getTimeout()))
|
|
|
+ // hide highlight of retweet header
|
|
|
+ .then(() => page.evaluate(() => (document.activeElement as unknown as HTMLOrSVGElement).blur()))
|
|
|
+ // determine screenshot height
|
|
|
+ .then(() =>
|
|
|
+ handle.$eval('article', article => article.clientHeight).then(height =>
|
|
|
+ handle.evaluate((div, minHeight) => {
|
|
|
+ div.parentElement.setAttribute('style', `min-height: ${minHeight}`);
|
|
|
+ div.setAttribute('style', 'margin: 0 -1px; padding: 0 1px');
|
|
|
+ }, height))
|
|
|
+ )
|
|
|
+ .then(() => handle.screenshot());
|
|
|
})
|
|
|
- .then(() => promisify(setTimeout)(getTimeout()))
|
|
|
- // hide highlight of retweet header
|
|
|
- .then(() => page.evaluate(() => (document.activeElement as unknown as HTMLOrSVGElement).blur()))
|
|
|
- .then(() => page.screenshot())
|
|
|
.then(screenshot => {
|
|
|
new PNG({
|
|
|
filterType: 4,
|
|
|
deflateLevel: 0,
|
|
|
}).on('parsed', function () {
|
|
|
- // remove comment area
|
|
|
- // tslint:disable-next-line: no-shadowed-variable
|
|
|
- // eslint-disable-next-line @typescript-eslint/no-shadow
|
|
|
- const idx = (x: number, y: number) => (this.width * y + x) << 2;
|
|
|
- let boundary: number = null;
|
|
|
- const x = zoomFactor * 2;
|
|
|
- for (let y = x; y < this.height; y += zoomFactor) {
|
|
|
- if (
|
|
|
- this.data[idx(x, y)] !== this.data[idx(x, y - zoomFactor)] &&
|
|
|
- this.data[idx(x, y)] === this.data[idx(x + zoomFactor * 10, y)]
|
|
|
- ) {
|
|
|
- boundary = y;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (boundary !== null) {
|
|
|
- logger.info(`found boundary at ${boundary}, cropping image`);
|
|
|
- this.data = this.data.slice(0, idx(this.width, boundary));
|
|
|
- this.height = boundary;
|
|
|
-
|
|
|
- sharpToFile(jpeg(this.pack())).then(path => {
|
|
|
- logger.info(`finished webshot for ${url}`);
|
|
|
- resolve({path, boundary});
|
|
|
- });
|
|
|
- } else if (height >= 8 * 1920) {
|
|
|
- logger.warn('too large, consider as a bug, returning');
|
|
|
- sharpToFile(jpeg(this.pack())).then(path => {
|
|
|
- resolve({path, boundary: 0});
|
|
|
- });
|
|
|
- } else {
|
|
|
- logger.info('unable to find boundary, try shooting a larger image');
|
|
|
- resolve({path: '', boundary});
|
|
|
- }
|
|
|
+ sharpToFile(jpeg(this.pack())).then(path => {
|
|
|
+ logger.info(`finished webshot for ${url}`);
|
|
|
+ resolve({path, boundary: this.height});
|
|
|
+ });
|
|
|
}).parse(screenshot);
|
|
|
})
|
|
|
.catch(err => {
|