From f6dc1f953e071be7fc88f2cb0727ab73c58ccf9a Mon Sep 17 00:00:00 2001 From: DarkCat09 Date: Mon, 11 Sep 2023 11:16:26 +0400 Subject: [PATCH 1/6] Moved engine selecting logic into separate function --- src/handlers/main.ts | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/handlers/main.ts b/src/handlers/main.ts index 61e0bb3..392b08e 100644 --- a/src/handlers/main.ts +++ b/src/handlers/main.ts @@ -4,6 +4,8 @@ import axios from "../types/axios"; import { JSDOM } from "jsdom"; import { DOMWindow } from "jsdom"; +import micromatch from "micromatch"; + import readability from "./readability"; import google, { GoogleDomains } from "./google"; import stackoverflow, { StackOverflowDomains } from "./stackoverflow/main"; @@ -11,8 +13,6 @@ import stackoverflow, { StackOverflowDomains } from "./stackoverflow/main"; import { generateProxyUrl } from "../utils/generate"; import isLocalResource from "../utils/islocal"; -import micromatch from "micromatch"; - import { LocalResourceError, NotHtmlMimetypeError } from "../errors/main"; export default async function handlePage( @@ -49,20 +49,19 @@ export default async function handlePage( } }); - if (engine) { - return engines[engine](window); + return getFallbackEngine(urlObj.hostname, engine)(window); +} + +function getFallbackEngine(host: string, specified?: string): EngineFunction { + if (specified) { + return engines[specified]; } - - const title = window.document.title; - const lang = window.document.documentElement.lang; - - for (const match of fallback) { - if (micromatch.isMatch(urlObj.hostname, match.pattern)) { - return { title, lang, ...match.engine(window) }; + for (const engine of fallback) { + if (micromatch.isMatch(host, engine.pattern)) { + return engine.engine; } } - - return engines.readability(window); + return engines.readability; } interface Engines { From 62d408ef98bc59cd7fb210ac0bcd49ef5639bc4d Mon Sep 17 00:00:00 2001 From: DarkCat09 Date: Mon, 11 Sep 2023 11:23:27 +0400 Subject: [PATCH 2/6] Refactor/cleanup: moved types to other file --- src/handlers/main.ts | 13 +------------ src/types/handlers.ts | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 12 deletions(-) create mode 100644 src/types/handlers.ts diff --git a/src/handlers/main.ts b/src/handlers/main.ts index 392b08e..9b1ce0f 100644 --- a/src/handlers/main.ts +++ b/src/handlers/main.ts @@ -1,8 +1,8 @@ import { IHandlerOutput } from "./handler.interface"; +import { Engines, EngineFunction, EnginesMatch } from "../types/handlers"; import axios from "../types/axios"; import { JSDOM } from "jsdom"; -import { DOMWindow } from "jsdom"; import micromatch from "micromatch"; @@ -64,23 +64,12 @@ function getFallbackEngine(host: string, specified?: string): EngineFunction { return engines.readability; } -interface Engines { - [key: string]: EngineFunction; -} - export const engines: Engines = { readability, google, stackoverflow, }; -type EngineFunction = (window: DOMWindow) => Promise; -export type EngineMatch = { - pattern: string | string[]; - engine: EngineFunction; -}; -export type EnginesMatch = EngineMatch[]; - export const engineList: string[] = Object.keys(engines); export const fallback: EnginesMatch = [ diff --git a/src/types/handlers.ts b/src/types/handlers.ts new file mode 100644 index 0000000..c5ec05e --- /dev/null +++ b/src/types/handlers.ts @@ -0,0 +1,14 @@ +import { DOMWindow } from "jsdom"; +import { IHandlerOutput } from "../handlers/handler.interface"; + +export interface Engines { + [key: string]: EngineFunction; +} + +export type EngineMatch = { + pattern: string | string[]; + engine: EngineFunction; +}; + +export type EngineFunction = (window: DOMWindow) => Promise; +export type EnginesMatch = EngineMatch[]; From 3a7abd93d99ad8ce1d96c1850dbbfc4e962503f2 Mon Sep 17 00:00:00 2001 From: DarkCat09 Date: Mon, 11 Sep 2023 12:59:19 +0400 Subject: [PATCH 3/6] Created HandlerInput class --- src/handlers/handler-input.ts | 46 +++++++++++++++++++++++++++++++++++ src/handlers/main.ts | 28 +++++++++------------ src/types/handlers.ts | 4 +-- 3 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 src/handlers/handler-input.ts diff --git a/src/handlers/handler-input.ts b/src/handlers/handler-input.ts new file mode 100644 index 0000000..72a13d1 --- /dev/null +++ b/src/handlers/handler-input.ts @@ -0,0 +1,46 @@ +import { JSDOM } from "jsdom"; +import { generateProxyUrl } from "../utils/generate"; + +export class HandlerInput { + private data: string; + private url: string; + private requestUrl: URL; + private engine?: string; + private redirectPath: string; + + constructor( + data: string, + url: string, + requestUrl: URL, + engine?: string, + redirectPath: string = "get", + ) { + this.data = data; + this.url = url; + this.requestUrl = requestUrl; + this.engine = engine; + this.redirectPath = redirectPath; + } + + parseDom() { + const dom = new JSDOM(this.data, { url: this.url }); + + const links = dom.window.document.getElementsByTagName("a"); + for (const link of links) { + try { + link.href = generateProxyUrl( + this.requestUrl, + link.href, + this.engine, + this.redirectPath, + ); + } catch (_err) { + // ignore TypeError: Invalid URL + } + } + } + + getUrl() { + return this.url; + } +} diff --git a/src/handlers/main.ts b/src/handlers/main.ts index 9b1ce0f..a6ff350 100644 --- a/src/handlers/main.ts +++ b/src/handlers/main.ts @@ -14,12 +14,13 @@ import { generateProxyUrl } from "../utils/generate"; import isLocalResource from "../utils/islocal"; import { LocalResourceError, NotHtmlMimetypeError } from "../errors/main"; +import { HandlerInput } from "./handler-input"; export default async function handlePage( url: string, // remote URL requestUrl: URL, // proxy URL engine?: string, - redirect_path: string = "get", + redirectPath: string = "get", ): Promise { const urlObj = new URL(url); @@ -34,22 +35,15 @@ export default async function handlePage( throw new NotHtmlMimetypeError(url); } - const window = new JSDOM(response.data, { url }).window; - - [...window.document.getElementsByTagName("a")].forEach((link) => { - try { - link.href = generateProxyUrl( - requestUrl, - link.href, - engine, - redirect_path, - ); - } catch (_err) { - // ignore TypeError: Invalid URL - } - }); - - return getFallbackEngine(urlObj.hostname, engine)(window); + return getFallbackEngine(urlObj.hostname, engine)( + new HandlerInput( + response.data, + url, + requestUrl, + engine, + redirectPath, + ) + ); } function getFallbackEngine(host: string, specified?: string): EngineFunction { diff --git a/src/types/handlers.ts b/src/types/handlers.ts index c5ec05e..846eeda 100644 --- a/src/types/handlers.ts +++ b/src/types/handlers.ts @@ -1,4 +1,4 @@ -import { DOMWindow } from "jsdom"; +import { HandlerInput } from "../handlers/handler-input"; import { IHandlerOutput } from "../handlers/handler.interface"; export interface Engines { @@ -10,5 +10,5 @@ export type EngineMatch = { engine: EngineFunction; }; -export type EngineFunction = (window: DOMWindow) => Promise; +export type EngineFunction = (input: HandlerInput) => Promise; export type EnginesMatch = EngineMatch[]; From 456a4720316c0d7440aa6e31a1c6f421a8353b0a Mon Sep 17 00:00:00 2001 From: DarkCat09 Date: Mon, 11 Sep 2023 13:01:27 +0400 Subject: [PATCH 4/6] Bugfix: parseDom return statement --- src/handlers/handler-input.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/handlers/handler-input.ts b/src/handlers/handler-input.ts index 72a13d1..1f2d260 100644 --- a/src/handlers/handler-input.ts +++ b/src/handlers/handler-input.ts @@ -22,7 +22,7 @@ export class HandlerInput { this.redirectPath = redirectPath; } - parseDom() { + parseDom(): JSDOM { const dom = new JSDOM(this.data, { url: this.url }); const links = dom.window.document.getElementsByTagName("a"); @@ -38,9 +38,11 @@ export class HandlerInput { // ignore TypeError: Invalid URL } } + + return dom; } - getUrl() { + getUrl(): string { return this.url; } } From bbbfe480ebeb7a3000d8a234e159e3eab4b83734 Mon Sep 17 00:00:00 2001 From: DarkCat09 Date: Mon, 11 Sep 2023 13:07:02 +0400 Subject: [PATCH 5/6] Adapted engines to work with HandlerInput --- src/handlers/google.ts | 8 +++++--- src/handlers/main.ts | 3 --- src/handlers/readability.ts | 6 +++--- src/handlers/stackoverflow/main.ts | 7 ++++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/handlers/google.ts b/src/handlers/google.ts index 7dd6be0..36a9cdc 100644 --- a/src/handlers/google.ts +++ b/src/handlers/google.ts @@ -1,12 +1,14 @@ -import { DOMWindow } from "jsdom"; +import { HandlerInput } from "./handler-input"; import { IHandlerOutput } from "./handler.interface"; import { EngineParseError } from "../errors/main"; export default async function google( - window: DOMWindow, + input: HandlerInput, ): Promise { + const document = input.parseDom().window.document; + const googleAnchors = [ - ...window.document.querySelectorAll("a[jsname=ACyKwe]"), + ...document.querySelectorAll("a[jsname=ACyKwe]"), ] as HTMLAnchorElement[]; if (!googleAnchors) { diff --git a/src/handlers/main.ts b/src/handlers/main.ts index a6ff350..8ff4ab9 100644 --- a/src/handlers/main.ts +++ b/src/handlers/main.ts @@ -2,15 +2,12 @@ import { IHandlerOutput } from "./handler.interface"; import { Engines, EngineFunction, EnginesMatch } from "../types/handlers"; import axios from "../types/axios"; -import { JSDOM } from "jsdom"; - import micromatch from "micromatch"; import readability from "./readability"; import google, { GoogleDomains } from "./google"; import stackoverflow, { StackOverflowDomains } from "./stackoverflow/main"; -import { generateProxyUrl } from "../utils/generate"; import isLocalResource from "../utils/islocal"; import { LocalResourceError, NotHtmlMimetypeError } from "../errors/main"; diff --git a/src/handlers/readability.ts b/src/handlers/readability.ts index f629aa2..a22cc66 100644 --- a/src/handlers/readability.ts +++ b/src/handlers/readability.ts @@ -1,12 +1,12 @@ import { Readability } from "@mozilla/readability"; +import { HandlerInput } from "./handler-input"; import { IHandlerOutput } from "./handler.interface"; -import { DOMWindow } from "jsdom"; import { EngineParseError } from "../errors/main"; export default async function readability( - window: DOMWindow + input: HandlerInput, ): Promise { - const reader = new Readability(window.document); + const reader = new Readability(input.parseDom().window.document); const parsed = reader.parse(); if (!parsed) { diff --git a/src/handlers/stackoverflow/main.ts b/src/handlers/stackoverflow/main.ts index 9730bc8..f1b9c6c 100644 --- a/src/handlers/stackoverflow/main.ts +++ b/src/handlers/stackoverflow/main.ts @@ -1,13 +1,14 @@ +import { HandlerInput } from "../handler-input"; import { IHandlerOutput } from "../handler.interface"; -import { DOMWindow } from "jsdom"; import { EngineParseError } from "../../errors/main"; import qPostsHandler from "./questions-posts"; export default async function stackoverflow( - window: DOMWindow, + input: HandlerInput, ): Promise { - const url = new URL(window.location.href); + const window = input.parseDom().window; + const url = new URL(window.location.href); const path = url.pathname.split("/").filter((p) => p !== ""); let result: IHandlerOutput = { From b847f40991efce973b0a8dc05ae3a25539844712 Mon Sep 17 00:00:00 2001 From: DarkCat09 Date: Mon, 11 Sep 2023 13:34:50 +0400 Subject: [PATCH 6/6] Bugfix: [Google] window is not defined --- src/handlers/google.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/handlers/google.ts b/src/handlers/google.ts index 36a9cdc..06568cc 100644 --- a/src/handlers/google.ts +++ b/src/handlers/google.ts @@ -5,10 +5,10 @@ import { EngineParseError } from "../errors/main"; export default async function google( input: HandlerInput, ): Promise { - const document = input.parseDom().window.document; + const window = input.parseDom().window; const googleAnchors = [ - ...document.querySelectorAll("a[jsname=ACyKwe]"), + ...window.document.querySelectorAll("a[jsname=ACyKwe]"), ] as HTMLAnchorElement[]; if (!googleAnchors) {