commit
6a906377a7
@ -1,10 +1,12 @@
|
|||||||
import { DOMWindow } from "jsdom";
|
import { HandlerInput } from "./handler-input";
|
||||||
import { IHandlerOutput } from "./handler.interface";
|
import { IHandlerOutput } from "./handler.interface";
|
||||||
import { EngineParseError } from "../errors/main";
|
import { EngineParseError } from "../errors/main";
|
||||||
|
|
||||||
export default async function google(
|
export default async function google(
|
||||||
window: DOMWindow,
|
input: HandlerInput,
|
||||||
): Promise<IHandlerOutput> {
|
): Promise<IHandlerOutput> {
|
||||||
|
const window = input.parseDom().window;
|
||||||
|
|
||||||
const googleAnchors = [
|
const googleAnchors = [
|
||||||
...window.document.querySelectorAll("a[jsname=ACyKwe]"),
|
...window.document.querySelectorAll("a[jsname=ACyKwe]"),
|
||||||
] as HTMLAnchorElement[];
|
] as HTMLAnchorElement[];
|
||||||
|
48
src/handlers/handler-input.ts
Normal file
48
src/handlers/handler-input.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
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(): JSDOM {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
getUrl(): string {
|
||||||
|
return this.url;
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,23 @@
|
|||||||
import { IHandlerOutput } from "./handler.interface";
|
import { IHandlerOutput } from "./handler.interface";
|
||||||
|
import { Engines, EngineFunction, EnginesMatch } from "../types/handlers";
|
||||||
import axios from "../types/axios";
|
import axios from "../types/axios";
|
||||||
|
|
||||||
import { JSDOM } from "jsdom";
|
import micromatch from "micromatch";
|
||||||
import { DOMWindow } from "jsdom";
|
|
||||||
|
|
||||||
import readability from "./readability";
|
import readability from "./readability";
|
||||||
import google, { GoogleDomains } from "./google";
|
import google, { GoogleDomains } from "./google";
|
||||||
import stackoverflow, { StackOverflowDomains } from "./stackoverflow/main";
|
import stackoverflow, { StackOverflowDomains } from "./stackoverflow/main";
|
||||||
|
|
||||||
import { generateProxyUrl } from "../utils/generate";
|
|
||||||
import isLocalResource from "../utils/islocal";
|
import isLocalResource from "../utils/islocal";
|
||||||
|
|
||||||
import micromatch from "micromatch";
|
|
||||||
|
|
||||||
import { LocalResourceError, NotHtmlMimetypeError } from "../errors/main";
|
import { LocalResourceError, NotHtmlMimetypeError } from "../errors/main";
|
||||||
|
import { HandlerInput } from "./handler-input";
|
||||||
|
|
||||||
export default async function handlePage(
|
export default async function handlePage(
|
||||||
url: string, // remote URL
|
url: string, // remote URL
|
||||||
requestUrl: URL, // proxy URL
|
requestUrl: URL, // proxy URL
|
||||||
engine?: string,
|
engine?: string,
|
||||||
redirect_path: string = "get",
|
redirectPath: string = "get",
|
||||||
): Promise<IHandlerOutput> {
|
): Promise<IHandlerOutput> {
|
||||||
const urlObj = new URL(url);
|
const urlObj = new URL(url);
|
||||||
|
|
||||||
@ -34,39 +32,27 @@ export default async function handlePage(
|
|||||||
throw new NotHtmlMimetypeError(url);
|
throw new NotHtmlMimetypeError(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
const window = new JSDOM(response.data, { url }).window;
|
return getFallbackEngine(urlObj.hostname, engine)(
|
||||||
|
new HandlerInput(
|
||||||
[...window.document.getElementsByTagName("a")].forEach((link) => {
|
response.data,
|
||||||
try {
|
url,
|
||||||
link.href = generateProxyUrl(
|
|
||||||
requestUrl,
|
requestUrl,
|
||||||
link.href,
|
|
||||||
engine,
|
engine,
|
||||||
redirect_path,
|
redirectPath,
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} catch (_err) {
|
|
||||||
// ignore TypeError: Invalid URL
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (engine) {
|
|
||||||
return engines[engine](window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = window.document.title;
|
function getFallbackEngine(host: string, specified?: string): EngineFunction {
|
||||||
const lang = window.document.documentElement.lang;
|
if (specified) {
|
||||||
|
return engines[specified];
|
||||||
for (const match of fallback) {
|
}
|
||||||
if (micromatch.isMatch(urlObj.hostname, match.pattern)) {
|
for (const engine of fallback) {
|
||||||
return { title, lang, ...match.engine(window) };
|
if (micromatch.isMatch(host, engine.pattern)) {
|
||||||
|
return engine.engine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return engines.readability;
|
||||||
return engines.readability(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Engines {
|
|
||||||
[key: string]: EngineFunction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const engines: Engines = {
|
export const engines: Engines = {
|
||||||
@ -75,13 +61,6 @@ export const engines: Engines = {
|
|||||||
stackoverflow,
|
stackoverflow,
|
||||||
};
|
};
|
||||||
|
|
||||||
type EngineFunction = (window: DOMWindow) => Promise<IHandlerOutput>;
|
|
||||||
export type EngineMatch = {
|
|
||||||
pattern: string | string[];
|
|
||||||
engine: EngineFunction;
|
|
||||||
};
|
|
||||||
export type EnginesMatch = EngineMatch[];
|
|
||||||
|
|
||||||
export const engineList: string[] = Object.keys(engines);
|
export const engineList: string[] = Object.keys(engines);
|
||||||
|
|
||||||
export const fallback: EnginesMatch = [
|
export const fallback: EnginesMatch = [
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { Readability } from "@mozilla/readability";
|
import { Readability } from "@mozilla/readability";
|
||||||
|
import { HandlerInput } from "./handler-input";
|
||||||
import { IHandlerOutput } from "./handler.interface";
|
import { IHandlerOutput } from "./handler.interface";
|
||||||
import { DOMWindow } from "jsdom";
|
|
||||||
import { EngineParseError } from "../errors/main";
|
import { EngineParseError } from "../errors/main";
|
||||||
|
|
||||||
export default async function readability(
|
export default async function readability(
|
||||||
window: DOMWindow
|
input: HandlerInput,
|
||||||
): Promise<IHandlerOutput> {
|
): Promise<IHandlerOutput> {
|
||||||
const reader = new Readability(window.document);
|
const reader = new Readability(input.parseDom().window.document);
|
||||||
const parsed = reader.parse();
|
const parsed = reader.parse();
|
||||||
|
|
||||||
if (!parsed) {
|
if (!parsed) {
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
|
import { HandlerInput } from "../handler-input";
|
||||||
import { IHandlerOutput } from "../handler.interface";
|
import { IHandlerOutput } from "../handler.interface";
|
||||||
import { DOMWindow } from "jsdom";
|
|
||||||
import { EngineParseError } from "../../errors/main";
|
import { EngineParseError } from "../../errors/main";
|
||||||
import qPostsHandler from "./questions-posts";
|
import qPostsHandler from "./questions-posts";
|
||||||
|
|
||||||
export default async function stackoverflow(
|
export default async function stackoverflow(
|
||||||
window: DOMWindow,
|
input: HandlerInput,
|
||||||
): Promise<IHandlerOutput> {
|
): Promise<IHandlerOutput> {
|
||||||
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 !== "");
|
const path = url.pathname.split("/").filter((p) => p !== "");
|
||||||
|
|
||||||
let result: IHandlerOutput = {
|
let result: IHandlerOutput = {
|
||||||
|
14
src/types/handlers.ts
Normal file
14
src/types/handlers.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { HandlerInput } from "../handlers/handler-input";
|
||||||
|
import { IHandlerOutput } from "../handlers/handler.interface";
|
||||||
|
|
||||||
|
export interface Engines {
|
||||||
|
[key: string]: EngineFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type EngineMatch = {
|
||||||
|
pattern: string | string[];
|
||||||
|
engine: EngineFunction;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EngineFunction = (input: HandlerInput) => Promise<IHandlerOutput>;
|
||||||
|
export type EnginesMatch = EngineMatch[];
|
Loading…
x
Reference in New Issue
Block a user