Compare commits
6 Commits
v8.2.3-alp
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67be3acc6e | ||
|
|
e92cb6ca8a | ||
|
|
85a45cf575 | ||
|
|
fe225e1090 | ||
|
|
6ed1567f0e | ||
|
|
67445ed648 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -10,4 +10,5 @@ p.ts
|
||||
.idea
|
||||
CHANGELOG.md
|
||||
theme.zip
|
||||
AGENTS.md
|
||||
AGENTS.md
|
||||
lustpress-express
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lustpress",
|
||||
"version": "8.2.3-alpha",
|
||||
"version": "8.3.6-alpha",
|
||||
"description": "RESTful and experimental API for PH and other R18 websites",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
|
||||
@@ -9,7 +9,7 @@ const keyv = process.env.REDIS_URL
|
||||
: new Keyv();
|
||||
|
||||
keyv.on("error", (err) => console.log("Connection Error", err));
|
||||
const ttl = 1000 * 60 * 60 * Number(process.env.EXPIRE_CACHE);
|
||||
const ttl = 1000 * 60 * 60 * Number(process.env.EXPIRE_CACHE || "1");
|
||||
|
||||
const GEO_TIMEOUT_MS = 3000;
|
||||
let cachedLastLocation: string | null = null;
|
||||
@@ -25,12 +25,14 @@ function cachedLocationOrUnknown(): string {
|
||||
class LustPress {
|
||||
url: string;
|
||||
useragent: string;
|
||||
private browserUA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36";
|
||||
private browserUA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36";
|
||||
private cookieCache: { [domain: string]: string } = {};
|
||||
|
||||
constructor() {
|
||||
this.url = "";
|
||||
this.useragent = `${pkg.name}/${pkg.version} Bun/${Bun.version}`;
|
||||
this.browserUA =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36";
|
||||
this.useragent = process.env.USER_AGENT || `${pkg.name}/${pkg.version} Bun/${Bun.version}`;
|
||||
}
|
||||
|
||||
async getPornhubCookies(): Promise<string> {
|
||||
@@ -77,13 +79,16 @@ class LustPress {
|
||||
|
||||
async fetchBody(url: string): Promise<Buffer> {
|
||||
const cached = await keyv.get(url);
|
||||
if (cached) return cached;
|
||||
if (cached) {
|
||||
console.log(`[CACHE HIT] ${url}`);
|
||||
return cached;
|
||||
}
|
||||
|
||||
const isPornhub = /pornhub\.com/i.test(url);
|
||||
const domain = new URL(url).hostname;
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
"User-Agent": isPornhub ? this.browserUA : this.useragent,
|
||||
"User-Agent": isPornhub ? this.browserUA : this.useragent
|
||||
};
|
||||
|
||||
if (isPornhub) {
|
||||
@@ -96,21 +101,25 @@ class LustPress {
|
||||
headers["Accept-Language"] = "en-US,en;q=0.9";
|
||||
}
|
||||
|
||||
console.log(`[FETCH] ${url}`);
|
||||
let res = await fetch(url, { headers, redirect: "follow" });
|
||||
let text = await res.text();
|
||||
let arrayBuf = await res.arrayBuffer();
|
||||
let body = Buffer.from(arrayBuf);
|
||||
|
||||
if (isPornhub && text.includes("leastFactor")) {
|
||||
if (isPornhub && body.toString("utf8").includes("leastFactor")) {
|
||||
console.log("Challenge detected at target URL. Re-authenticating...");
|
||||
this.cookieCache[domain] = await this.getPornhubCookies();
|
||||
res = await fetch(url, {
|
||||
headers: { ...headers, Cookie: this.cookieCache[domain] },
|
||||
redirect: "follow"
|
||||
});
|
||||
text = await res.text();
|
||||
arrayBuf = await res.arrayBuffer();
|
||||
body = Buffer.from(arrayBuf);
|
||||
}
|
||||
|
||||
const body = Buffer.from(text);
|
||||
if (!url.includes("/random")) await keyv.set(url, body, ttl);
|
||||
if (res.ok && !url.includes("/random")) {
|
||||
await keyv.set(url, body, ttl);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
|
||||
125
src/index.ts
125
src/index.ts
@@ -1,56 +1,69 @@
|
||||
import { Elysia } from "elysia";
|
||||
import { cors } from "@elysiajs/cors";
|
||||
import { swagger } from "@elysiajs/swagger";
|
||||
import { lust } from "./LustPress";
|
||||
import { scrapeRoutes } from "./router/endpoint";
|
||||
import pkg from "../package.json";
|
||||
|
||||
const app = new Elysia()
|
||||
.use(cors())
|
||||
.use(
|
||||
swagger({
|
||||
path: "/docs",
|
||||
documentation: {
|
||||
info: {
|
||||
title: "Lustpress API",
|
||||
version: pkg.version,
|
||||
description: pkg.description,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.get("/", async () => ({
|
||||
success: true,
|
||||
playground: "https://sinkaroid.github.io/lustpress",
|
||||
endpoint:
|
||||
"https://github.com/sinkaroid/lustpress/blob/master/README.md#routing",
|
||||
date: new Date().toLocaleString(),
|
||||
rss: lust.currentProccess().rss,
|
||||
heap: lust.currentProccess().heap,
|
||||
server: await lust.getServer(),
|
||||
version: pkg.version,
|
||||
}))
|
||||
.use(scrapeRoutes)
|
||||
.onError(({ code, error, set }) => {
|
||||
console.log("Error occurred:", error);
|
||||
if (code === "NOT_FOUND") {
|
||||
set.status = 404;
|
||||
return {
|
||||
success: false,
|
||||
message: (error as Error).message || "Not Found",
|
||||
};
|
||||
}
|
||||
set.status = 500;
|
||||
return {
|
||||
success: false,
|
||||
message: (error as Error).message || "Internal Server Error",
|
||||
stack: (error as Error).stack,
|
||||
};
|
||||
})
|
||||
.listen(process.env.PORT || 3000);
|
||||
|
||||
console.log(
|
||||
`Lustpress is running at ${app.server?.hostname}:${app.server?.port}`
|
||||
);
|
||||
|
||||
export type App = typeof app;
|
||||
import { Elysia } from "elysia";
|
||||
import { cors } from "@elysiajs/cors";
|
||||
import { swagger } from "@elysiajs/swagger";
|
||||
import { lust } from "./LustPress";
|
||||
import { scrapeRoutes } from "./router/endpoint";
|
||||
import pkg from "../package.json";
|
||||
|
||||
const app = new Elysia()
|
||||
.use(cors())
|
||||
.use(
|
||||
swagger({
|
||||
path: "/docs",
|
||||
documentation: {
|
||||
info: {
|
||||
title: "Lustpress API",
|
||||
version: pkg.version,
|
||||
description: pkg.description,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.get("/", async () => ({
|
||||
success: true,
|
||||
playground: "https://sinkaroid.github.io/lustpress",
|
||||
endpoint:
|
||||
"https://github.com/sinkaroid/lustpress/blob/master/README.md#routing",
|
||||
date: new Date().toLocaleString(),
|
||||
rss: lust.currentProccess().rss,
|
||||
heap: lust.currentProccess().heap,
|
||||
server: await lust.getServer(),
|
||||
version: pkg.version,
|
||||
}))
|
||||
.onError(({ code, error, set }) => {
|
||||
if (code === "NOT_FOUND") {
|
||||
set.status = 404;
|
||||
return {
|
||||
success: false,
|
||||
message: (error as Error).message || "Not Found",
|
||||
};
|
||||
}
|
||||
if (code === "VALIDATION") {
|
||||
set.status = 400;
|
||||
return {
|
||||
success: false,
|
||||
message: JSON.parse((error as Error).message)[0]?.message || "Validation Error",
|
||||
};
|
||||
}
|
||||
if (code === "UNKNOWN") {
|
||||
set.status = 400;
|
||||
return {
|
||||
success: false,
|
||||
message: (error as Error).message,
|
||||
};
|
||||
}
|
||||
set.status = 500;
|
||||
return {
|
||||
success: false,
|
||||
message: (error as Error).message || "Internal Server Error",
|
||||
stack: (error as Error).stack,
|
||||
};
|
||||
})
|
||||
.use(scrapeRoutes) // reuse legacy error handling
|
||||
.listen(process.env.PORT || 3000);
|
||||
|
||||
console.log(
|
||||
`Lustpress is running at ${app.server?.hostname}:${app.server?.port}`
|
||||
);
|
||||
|
||||
export type App = typeof app;
|
||||
|
||||
Reference in New Issue
Block a user