From 62ba4b7644c1006033344bf5e800a33bfd7b4cbf Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:07:27 +0700 Subject: [PATCH 01/17] docs: make sec policy to the main repo --- SECURITY.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..73bbb48 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Lustpress Security + +## Reporting vulnerabilities + +To report sensitive vulnerabilities, alert the author by email at anakmancasan@gmail.com. \ No newline at end of file From 0ca3d8edabafcaad30a41a6b0156538f4b184016 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:08:03 +0700 Subject: [PATCH 02/17] docs: add code of conduct and contributing guidelines --- CODE_OF_CONDUCT.md | 76 ++++++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 10 ++++++ 2 files changed, 86 insertions(+) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..e133e5b --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at anakmancasan@gmail.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..9a893b8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,10 @@ +# Contributing + +## Making major changes +Please first discuss the change you wish to make via issue, +email, or any other method with the owners before making a change. + +Please note we have a code of conduct, follow it in all your interactions with the project. + +## Making minor changes +@sinkaroid are not the best coder, so there are sure some problematic coding decision, every slight of changes will helps however. I always happy to receive Pull requests to improve things. \ No newline at end of file From 0ce3513713ca31a79affbafc8ece59c79e7b5cd9 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:08:36 +0700 Subject: [PATCH 03/17] docs: add closing remarks and acknowledgements --- CLOSING_REMARKS.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 CLOSING_REMARKS.md diff --git a/CLOSING_REMARKS.md b/CLOSING_REMARKS.md new file mode 100644 index 0000000..b5d1e18 --- /dev/null +++ b/CLOSING_REMARKS.md @@ -0,0 +1,22 @@ +# Closing remarks + +I hope you have found this project useful. All the major credit really goes to the all the doujin sites, which +allows this services to operate. + +- [PornHub](https://pornhub.com) +- [Xnxx](https://xnxx.com) +- [RedTube](https://redtube.com) +- [Xvideos](https://xvideos.com) +- [Xhamster](https://xhamster.com) +- [YouPorn](https://youporn.com) +- [JavHD](https://javhd.com) + +Core dependencies: +- [express](https://github.com/expressjs/express) +- [cheerio](https://cheerio.js.org/) +- [keyv](https://github.com/jaredwray/keyv) + +# Alternative-links +Just in case if https://lust.scathach.id down, here some alternative deployment + +- TBA From d0a91acd04f5df663d033874bfba96dae21ac2f2 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:09:43 +0700 Subject: [PATCH 04/17] style: add eslint and eslintignore target --- .eslintignore | 2 ++ .eslintrc.json | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 .eslintignore create mode 100644 .eslintrc.json diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..b51ea71 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +node_modules/ +build/ \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..bcf3255 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,41 @@ +{ + "env": { + "es2021": true, + "node": true, + "commonjs": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 12, + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint" + ], + "rules": { + "linebreak-style": 0, + "quotes": [ + "error", + "double" + ], + "semi": [ + "error", + "always" + ], + "no-empty": "error", + "no-func-assign": "error", + "no-case-declarations": "off", + "no-unreachable": "error", + "no-eval": "error", + "no-global-assign": "error", + "@typescript-eslint/no-explicit-any": ["off"], + "indent": [ + "error", + 2 + ] + } +} \ No newline at end of file From a785a3045c5cead287a3a5e63572ce1ac0081641 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:10:47 +0700 Subject: [PATCH 05/17] chore: add .env.schema value example --- .env.schema | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .env.schema diff --git a/.env.schema b/.env.schema new file mode 100644 index 0000000..b480e71 --- /dev/null +++ b/.env.schema @@ -0,0 +1,14 @@ +# railway, fly.dev, heroku, vercel or any free service +RAILWAY = sinkaroid + +# default port +PORT = 3000 + +# backend storage, default is redis, if not set it will consume memory storage +REDIS_URL = redis://default:somenicepassword@redis-666.c10.us-east-6-6.ec666.cloud.redislabs.com:1337 + +# ttl expire cache (in X hour) +EXPIRE_CACHE = 1 + +# you must identify your origin, if not set it will use default +USER_AGENT = "lustpress/1.6.0 Node.js/16.9.1" \ No newline at end of file From 7242a81c69134865e5887b0709cb9ca734606b76 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:11:42 +0700 Subject: [PATCH 06/17] build: dockerized lustpress and add .dockerignore --- .dockerignore | 2 ++ Dockerfile | 9 +++++++++ 2 files changed, 11 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5171c54 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +node_modules +npm-debug.log \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bc73214 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM node:latest + +WORKDIR /srv/app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build +EXPOSE 3000 +CMD ["node", "build/src/index.js"] \ No newline at end of file From c87412b44b2ea339b4a0250f0d2e1b6fe2e07891 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:12:41 +0700 Subject: [PATCH 07/17] feat: add interfaces --- src/interfaces.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/interfaces.ts diff --git a/src/interfaces.ts b/src/interfaces.ts new file mode 100644 index 0000000..5131eb2 --- /dev/null +++ b/src/interfaces.ts @@ -0,0 +1,29 @@ +export interface IVideoData { + success: boolean; + data: { + title: string; + id: string; + image: string; + duration: string; + views: string; + rating: string; + uploaded: string; + upvoted: string | null; + downvoted: string | null; + models: string[]; + tags: string[]; + }; + source: string; + assets: string[]; +} + +export interface ISearchVideoData { + success: boolean; + data: string[]; + source: string; +} + +export interface MaybeError { + message: string; +} + From 789ed006101104f34861990168b7a3ab4c6a7bef Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:13:02 +0700 Subject: [PATCH 08/17] feat: add index bindings --- src/index.ts | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/index.ts diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..74193cf --- /dev/null +++ b/src/index.ts @@ -0,0 +1,52 @@ +import "dotenv/config"; +import LustPress from "./LustPress"; +import express from "express"; +import { Request, Response, NextFunction } from "express"; +import scrapeRoutes from "./router/endpoint"; +import { slow, limiter } from "./utils/limit-options"; +import { logger } from "./utils/logger"; +import * as pkg from "../package.json"; + +const lust = new LustPress(); +const app = express(); + + +app.get("/", slow, limiter, async (req, res) => { + res.send({ + 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}`, + }); + logger.info({ + path: req.path, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); +}); + +app.use(scrapeRoutes()); +app.use((req: Request, res: Response, next: NextFunction) => { + res.status(404); + next(Error(`The page not found in path ${req.url} and method ${req.method}`)); + logger.error({ + path: req.url, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); +}); + +app.use((error: any, res: Response) => { + res.status(500).json({ + message: error.message, + stack: error.stack + }); +}); + +app.listen(process.env.PORT || 3000, () => console.log(`${pkg.name} is running on port ${process.env.PORT || 3000}`)); \ No newline at end of file From eeea8c62da466c6efa0ce1affc423ec7ef584567 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:13:27 +0700 Subject: [PATCH 09/17] feat: add main class --- src/LustPress.ts | 153 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/LustPress.ts diff --git a/src/LustPress.ts b/src/LustPress.ts new file mode 100644 index 0000000..49168e6 --- /dev/null +++ b/src/LustPress.ts @@ -0,0 +1,153 @@ +import p, { IResponse } from "phin"; +import Keyv from "keyv"; +import pkg from "../package.json"; + + +const keyv = new Keyv(process.env.REDIS_URL); + +keyv.on("error", err => console.log("Connection Error", err)); +const ttl = 1000 * 60 * 60 * Number(process.env.EXPIRE_CACHE); + + +class LustPress { + url: string; + useragent: string; + constructor() { + this.url = ""; + this.useragent = `${pkg.name}/${pkg.version} Node.js/16.9.1`; + } + + /** + * Fetch body from url and check if it's cached + * @param url url to fetch + * @returns Buffer + */ + async fetchBody(url: string): Promise { + const cached = await keyv.get(url); + + if (cached) { + console.log("Fetching from cache"); + return cached; + } else if (url.includes("/random")) { + console.log("Random should not be cached"); + const res = await p({ + url: url, + "headers": { + "User-Agent": process.env.USER_AGENT || `${pkg.name}/${pkg.version} Node.js/16.9.1`, + }, + followRedirects: true + }); + return res.body; + } else { + console.log("Fetching from source"); + const res = await p({ + url: url, + "headers": { + "User-Agent": process.env.USER_AGENT || `${pkg.name}/${pkg.version} Node.js/16.9.1`, + }, + followRedirects: true + }); + await keyv.set(url, res.body, ttl); + return res.body; + } + } + + /** + * remove html tag and bunch of space + * @param str string to remove html tag + * @returns string + */ + removeHtmlTag(str: string): string { + str = str.replace(/(\r\n|\n|\r)/gm, ""); + str = str.replace(/\s+/g, ""); + return str; + } + + /** + * remove html tag without space + * @param str string to remove html tag + * @returns string + */ + removeHtmlTagWithoutSpace(str: string): string { + str = str.replace(/(\r\n|\n|\r|\t)/gm, ""); + str = str.replace(/\\/g, ""); + return str.trim(); + } + + /** + * remove all single quote on array + * @param arr array to remove single quote + * @returns string[] + */ + removeAllSingleQuoteOnArray(arr: string[]): string[] { + return arr.map((item) => item.replace(/'/g, "")); + } + + /** + * time ago converter + * @param input date to convert + * @returns string + */ + timeAgo(input: Date) { + const date = new Date(input); + const formatter: any = new Intl.RelativeTimeFormat("en"); + const ranges: { [key: string]: number } = { + years: 3600 * 24 * 365, + months: 3600 * 24 * 30, + weeks: 3600 * 24 * 7, + days: 3600 * 24, + hours: 3600, + minutes: 60, + seconds: 1 + }; + const secondsElapsed = (date.getTime() - Date.now()) / 1000; + for (const key in ranges) { + if (ranges[key] < Math.abs(secondsElapsed)) { + const delta = secondsElapsed / ranges[key]; + return formatter.format(Math.round(delta), key); + } + } + } + + /** + * convert seconds to minute + * @param seconds seconds to convert + * @returns string + */ + secondToMinute(seconds: number): string { + const minutes = Math.floor(seconds / 60); + const second = seconds % 60; + return `${minutes}min, ${second}sec`; + } + + /** + * get current process memory usage + * @returns object + */ + currentProccess() { + const arr = [1, 2, 3, 4, 5, 6, 9, 7, 8, 9, 10]; + arr.reverse(); + const rss = process.memoryUsage().rss / 1024 / 1024; + const heap = process.memoryUsage().heapUsed / 1024 / 1024; + const heaptotal = process.memoryUsage().heapTotal / 1024 / 1024; + return { + rss: `${Math.round(rss * 100) / 100} MB`, + heap: `${Math.round(heap * 100) / 100}/${Math.round(heaptotal * 100) / 100} MB` + }; + } + + /** + * fetch this server location + * @returns > + */ + async getServer(): Promise { + const raw = await p({ + "url": "http://ip-api.com/json", + "parse": "json" + }) as IResponse; + const data = raw.body as unknown as { country: string, regionName: string }; + return `${data.country}, ${data.regionName}`; + } +} + +export default LustPress; From 23e8b57273e4608800281d87640b217809e41e82 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:14:49 +0700 Subject: [PATCH 10/17] ci: tdd --- .github/workflows/pornhub.yml | 30 +++++++++++++++ .github/workflows/status.yml | 29 +++++++++++++++ package.json | 69 +++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 .github/workflows/pornhub.yml create mode 100644 .github/workflows/status.yml create mode 100644 package.json diff --git a/.github/workflows/pornhub.yml b/.github/workflows/pornhub.yml new file mode 100644 index 0000000..bdab147 --- /dev/null +++ b/.github/workflows/pornhub.yml @@ -0,0 +1,30 @@ +name: Pornhub test + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [14.x] + + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - name: Install dependencies + run: npm install + - name: Build + run: npm run build + + - name: Pornhub test + run: npm run test:pornhub \ No newline at end of file diff --git a/.github/workflows/status.yml b/.github/workflows/status.yml new file mode 100644 index 0000000..70b4a8b --- /dev/null +++ b/.github/workflows/status.yml @@ -0,0 +1,29 @@ +name: Check status + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [14.x] + + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - name: Install dependencies + run: npm install + - name: Build + run: npm run build + - name: Check status code + run: npm run test \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..ec75306 --- /dev/null +++ b/package.json @@ -0,0 +1,69 @@ +{ + "name": "lustpress", + "version": "1.6.0-alpha", + "description": "RESTful and experimental API for PornHub and other porn sites, which official is lack even isn't exist.", + "main": "build/src/index.js", + "scripts": { + "build": "rimraf build && tsc", + "start": "node build/src/index.js", + "test": "ts-node test/test.ts", + "test:mock": "ts-node test/mock.ts", + "start:prod": "npm run build && node build/src/index.js", + "start:dev": "ts-node-dev src/index.ts", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --fix", + "build:freshdoc": "rimraf docs && rimraf template && rimraf theme.zip", + "build:template": " npm run build:freshdoc && curl https://codeload.github.com/ScathachGrip/apidocjs-theme/zip/refs/tags/v11 -o theme.zip && unzip theme.zip && mv apidocjs-theme-11 template", + "build:apidoc": "npm run build:template && apidoc -i src -o ./docs -t ./template/template-scarlet", + "test:pornhub": "start-server-and-test 3000 \"curl -v http://localhost:3000/pornhub/random | jq '.'\"", + "test:xnxx": "start-server-and-test 3000 \"curl -v http://localhost:3000/xnxx/random | jq '.'\"", + "test:redtube": "start-server-and-test 3000 \"curl -v http://localhost:3000/redtube/random | jq '.'\"", + "test:xvideos": "start-server-and-test 3000 \"curl -v http://localhost:3000/xvideos/random | jq '.'\"", + "test:xhamster": "start-server-and-test 3000 \"curl -v http://localhost:3000/xhamster/random | jq '.'\"", + "test:youporn": "start-server-and-test 3000 \"curl -v http://localhost:3000/youporn/random | jq '.'\"" + }, + "apidoc": { + "title": "Lustpress API Documentation", + "url": "https://lust.scathach.id", + "sampleUrl": "https://lust.scathach.id", + "name": "Lustpress" + }, + "keywords": [], + "author": "sinkaroid", + "repository": { + "type": "git", + "url": "git+https://github.com/sinkaroid/lustpress.git" + }, + "license": "MIT", + "dependencies": { + "@keyv/redis": "^2.5.7", + "cheerio": "^1.0.0-rc.12", + "cors": "^2.8.5", + "dotenv": "^16.0.3", + "express": "^4.18.2", + "express-rate-limit": "^6.7.0", + "express-slow-down": "^1.6.0", + "keyv": "^4.5.2", + "phin": "^3.7.0", + "pino": "^8.11.0", + "pino-pretty": "^10.0.0" + }, + "devDependencies": { + "@types/cors": "^2.8.13", + "@types/express": "^4.17.17", + "@types/express-slow-down": "^1.3.2", + "@types/node": "^18.15.11", + "@typescript-eslint/eslint-plugin": "^5.58.0", + "@typescript-eslint/parser": "^5.58.0", + "apidoc": "0.29.0", + "eslint": "^8.38.0", + "rimraf": "^5.0.0", + "start-server-and-test": "^2.0.0", + "ts-node": "^10.9.1", + "ts-node-dev": "^2.0.0", + "typescript": "5.0.4" + }, + "engines": { + "node": ">=14" + } +} From ce45eea025e89d90a0666246927aef04a01824b1 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:17:37 +0700 Subject: [PATCH 11/17] test: add some testing and prototype --- src/utils/options.ts | 9 +++++++++ test/test.ts | 14 ++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/utils/options.ts create mode 100644 test/test.ts diff --git a/src/utils/options.ts b/src/utils/options.ts new file mode 100644 index 0000000..ffcdbb3 --- /dev/null +++ b/src/utils/options.ts @@ -0,0 +1,9 @@ +export default { + PORNHUB: "https://www.pornhub.com", + XNXX: "https://www.xnxx.com", + REDTUBE: "https://www.redtube.com", + XVIDEOS: "https://www.xvideos.com", + XHAMSTER: "https://xheve2.com", + YOUPORN: "https://www.youporn.com", + JAVHD: "https://javhd.today" +}; \ No newline at end of file diff --git a/test/test.ts b/test/test.ts new file mode 100644 index 0000000..2bd6a71 --- /dev/null +++ b/test/test.ts @@ -0,0 +1,14 @@ +import c from "../src/utils/options"; +import p from "phin"; + +for (const url of + [c.PORNHUB, c.XNXX, c.REDTUBE, c.XVIDEOS, c.XHAMSTER, c.YOUPORN]) { + p({ url }).then(res => { + if (res.statusCode !== 200) { + console.log(`${url} is not available, status code: ${res.statusCode}, check the sites or your own user-agent`); + } + else { + console.log(`${url} is available, can be scraped`); + } + }); +} \ No newline at end of file From da29c289493532da722d4da692163521f696c491 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:19:14 +0700 Subject: [PATCH 12/17] test: add some testing and prototype --- test/mock.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 test/mock.ts diff --git a/test/mock.ts b/test/mock.ts new file mode 100644 index 0000000..78a6e1b --- /dev/null +++ b/test/mock.ts @@ -0,0 +1,20 @@ +import p from "phin"; +import { load } from "cheerio"; + +const url = "https://www.pornhub.com/view_video.php?viewkey=ph63c4e1dc48fe7"; + +async function test() { + const res = await p({ + url: url, + "headers": { + "User-Agent": process.env.USER_AGENT || "lustpress/1.6.0 Node.js/16.9.1", + }, + }); + + const $ = load(res.body); + const title = $("meta[property='og:title']").attr("content"); + console.log(title); + console.log(res.statusCode); +} + +test().catch(console.error); From aade7ca2f7a9bbbc3e1330996d1e116e28fccf6f Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:19:55 +0700 Subject: [PATCH 13/17] feat: add logs, modifier and throttling stuff --- src/utils/limit-options.ts | 17 +++++++++++++++++ src/utils/logger.ts | 8 ++++++++ src/utils/modifier.ts | 39 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 src/utils/limit-options.ts create mode 100644 src/utils/logger.ts create mode 100644 src/utils/modifier.ts diff --git a/src/utils/limit-options.ts b/src/utils/limit-options.ts new file mode 100644 index 0000000..c9ddf55 --- /dev/null +++ b/src/utils/limit-options.ts @@ -0,0 +1,17 @@ +import rateLimit from "express-rate-limit"; +import slowDown from "express-slow-down"; + +const limiter = rateLimit({ + windowMs: 15 * 60 * 1000, + max: 50, + message: "Too nasty, please slow down" +}); + +const slow = slowDown({ + delayAfter: 50, + windowMs: 15 * 60 * 1000, + delayMs: 1000, + maxDelayMs: 20000, +}); + +export { limiter, slow }; \ No newline at end of file diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 0000000..99cef2d --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,8 @@ +import pino from "pino"; + +export const logger = pino({ + level: "info", + transport: { + target: "pino-pretty" + }, +}); \ No newline at end of file diff --git a/src/utils/modifier.ts b/src/utils/modifier.ts new file mode 100644 index 0000000..70fad88 --- /dev/null +++ b/src/utils/modifier.ts @@ -0,0 +1,39 @@ +/** + * Auto space on url + * @param str the string to be spaced + * @returns string + */ +export function spacer(str: string) { + return str.replace(/\s/g, "+"); +} + +/** + * Error handler + * @param success when success is false, it will return error + * @param message error message + * @returns object + */ +export function maybeError(success: boolean, message: string) { + return { success, message }; +} + +export function timeAgo(input: Date) { + const date = new Date(input); + const formatter: any = new Intl.RelativeTimeFormat("en"); + const ranges: { [key: string]: number } = { + years: 3600 * 24 * 365, + months: 3600 * 24 * 30, + weeks: 3600 * 24 * 7, + days: 3600 * 24, + hours: 3600, + minutes: 60, + seconds: 1 + }; + const secondsElapsed = (date.getTime() - Date.now()) / 1000; + for (const key in ranges) { + if (ranges[key] < Math.abs(secondsElapsed)) { + const delta = secondsElapsed / ranges[key]; + return formatter.format(Math.round(delta), key); + } + } +} \ No newline at end of file From 62005c451834f7bde0f1225ced17e7a4e7e67321 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:22:52 +0700 Subject: [PATCH 14/17] feat: add endpoint router --- src/router/endpoint.ts | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/router/endpoint.ts diff --git a/src/router/endpoint.ts b/src/router/endpoint.ts new file mode 100644 index 0000000..8303d73 --- /dev/null +++ b/src/router/endpoint.ts @@ -0,0 +1,72 @@ +import cors from "cors"; +import { Router } from "express"; +import { slow, limiter } from "../utils/limit-options"; + +// PornHub +import { getPornhub } from "../controller/pornhub/pornhubGet"; +import { searchPornhub } from "../controller/pornhub/pornhubSearch"; +import { randomPornhub } from "../controller/pornhub/pornhubRandom"; +import { relatedPornhub } from "../controller/pornhub/pornhubGetRelated"; + +// XNXX +import { getXnxx } from "../controller/xnxx/xnxxGet"; +import { searchXnxx } from "../controller/xnxx/xnxxSearch"; +import { relatedXnxx } from "../controller/xnxx/xnxxGetRelated"; +import { randomXnxx } from "../controller/xnxx/xnxxRandom"; + +// RedTube +import { getRedtube } from "../controller/redtube/redtubeGet"; +import { searchRedtube } from "../controller/redtube/redtubeSearch"; +import { relatedRedtube } from "../controller/redtube/redtubeGetRelated"; +import { randomRedtube } from "../controller/redtube/redtubeRandom"; + +// Xvideos +import { getXvideos } from "../controller/xvideos/xvideosGet"; +import { searchXvideos } from "../controller/xvideos/xvideosSearch"; +import { randomXvideos } from "../controller/xvideos/xvideosRandom"; +import { relatedXvideos } from "../controller/xvideos/xvideosGetRelated"; + +// Xhamster +import { getXhamster } from "../controller/xhamster/xhamsterGet"; +import { searchXhamster } from "../controller/xhamster/xhamsterSearch"; +import { randomXhamster } from "../controller/xhamster/xhamsterRandom"; +import { relatedXhamster } from "../controller/xhamster/xhamsterGetRelated"; + +// YouPorn +import { getYouporn } from "../controller/youporn/youpornGet"; +import { searchYouporn } from "../controller/youporn/youpornSearch"; +import { relatedYouporn } from "../controller/youporn/youpornGetRelated"; +import { randomYouporn } from "../controller/youporn/youpornRandom"; + +function scrapeRoutes() { + const router = Router(); + + router.get("/pornhub/get", cors(), slow, limiter, getPornhub); + router.get("/pornhub/search", cors(), slow, limiter, searchPornhub); + router.get("/pornhub/random", cors(), slow, limiter, randomPornhub); + router.get("/pornhub/related", cors(), slow, limiter, relatedPornhub); + router.get("/xnxx/get", cors(), slow, limiter, getXnxx); + router.get("/xnxx/search", cors(), slow, limiter, searchXnxx); + router.get("/xnxx/related", cors(), slow, limiter, relatedXnxx); + router.get("/xnxx/random", cors(), slow, limiter, randomXnxx); + router.get("/redtube/get", cors(), slow, limiter, getRedtube); + router.get("/redtube/search", cors(), slow, limiter, searchRedtube); + router.get("/redtube/related", cors(), slow, limiter, relatedRedtube); + router.get("/redtube/random", cors(), slow, limiter, randomRedtube); + router.get("/xvideos/get", cors(), slow, limiter, getXvideos); + router.get("/xvideos/search", cors(), slow, limiter, searchXvideos); + router.get("/xvideos/random", cors(), slow, limiter, randomXvideos); + router.get("/xvideos/related", cors(), slow, limiter, relatedXvideos); + router.get("/xhamster/get", cors(), slow, limiter, getXhamster); + router.get("/xhamster/search", cors(), slow, limiter, searchXhamster); + router.get("/xhamster/random", cors(), slow, limiter, randomXhamster); + router.get("/xhamster/related", cors(), slow, limiter, relatedXhamster); + router.get("/youporn/get", cors(), slow, limiter, getYouporn); + router.get("/youporn/search", cors(), slow, limiter, searchYouporn); + router.get("/youporn/related", cors(), slow, limiter, relatedYouporn); + router.get("/youporn/random", cors(), slow, limiter, randomYouporn); + + return router; +} + +export default scrapeRoutes; \ No newline at end of file From 3603e016cffbf728342af8099e6af5200a59c2df Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:24:00 +0700 Subject: [PATCH 15/17] feat(controller): add each endpoint controller --- src/controller/pornhub/pornhubGet.ts | 55 ++++++++++++++++ src/controller/pornhub/pornhubGetRelated.ts | 55 ++++++++++++++++ src/controller/pornhub/pornhubRandom.ts | 50 ++++++++++++++ src/controller/pornhub/pornhubSearch.ts | 66 +++++++++++++++++++ src/controller/redtube/redtubeGet.ts | 56 ++++++++++++++++ src/controller/redtube/redtubeGetRelated.ts | 54 +++++++++++++++ src/controller/redtube/redtubeRandom.ts | 65 ++++++++++++++++++ src/controller/redtube/redtubeSearch.ts | 58 ++++++++++++++++ src/controller/xhamster/xhamsterGet.ts | 55 ++++++++++++++++ src/controller/xhamster/xhamsterGetRelated.ts | 55 ++++++++++++++++ src/controller/xhamster/xhamsterRandom.ts | 63 ++++++++++++++++++ src/controller/xhamster/xhamsterSearch.ts | 58 ++++++++++++++++ src/controller/xnxx/xnxxGet.ts | 55 ++++++++++++++++ src/controller/xnxx/xnxxGetRelated.ts | 55 ++++++++++++++++ src/controller/xnxx/xnxxRandom.ts | 63 ++++++++++++++++++ src/controller/xnxx/xnxxSearch.ts | 58 ++++++++++++++++ src/controller/xvideos/xvideosGet.ts | 55 ++++++++++++++++ src/controller/xvideos/xvideosGetRelated.ts | 55 ++++++++++++++++ src/controller/xvideos/xvideosRandom.ts | 63 ++++++++++++++++++ src/controller/xvideos/xvideosSearch.ts | 58 ++++++++++++++++ src/controller/youporn/youpornGet.ts | 55 ++++++++++++++++ src/controller/youporn/youpornGetRelated.ts | 55 ++++++++++++++++ src/controller/youporn/youpornRandom.ts | 62 +++++++++++++++++ src/controller/youporn/youpornSearch.ts | 58 ++++++++++++++++ 24 files changed, 1382 insertions(+) create mode 100644 src/controller/pornhub/pornhubGet.ts create mode 100644 src/controller/pornhub/pornhubGetRelated.ts create mode 100644 src/controller/pornhub/pornhubRandom.ts create mode 100644 src/controller/pornhub/pornhubSearch.ts create mode 100644 src/controller/redtube/redtubeGet.ts create mode 100644 src/controller/redtube/redtubeGetRelated.ts create mode 100644 src/controller/redtube/redtubeRandom.ts create mode 100644 src/controller/redtube/redtubeSearch.ts create mode 100644 src/controller/xhamster/xhamsterGet.ts create mode 100644 src/controller/xhamster/xhamsterGetRelated.ts create mode 100644 src/controller/xhamster/xhamsterRandom.ts create mode 100644 src/controller/xhamster/xhamsterSearch.ts create mode 100644 src/controller/xnxx/xnxxGet.ts create mode 100644 src/controller/xnxx/xnxxGetRelated.ts create mode 100644 src/controller/xnxx/xnxxRandom.ts create mode 100644 src/controller/xnxx/xnxxSearch.ts create mode 100644 src/controller/xvideos/xvideosGet.ts create mode 100644 src/controller/xvideos/xvideosGetRelated.ts create mode 100644 src/controller/xvideos/xvideosRandom.ts create mode 100644 src/controller/xvideos/xvideosSearch.ts create mode 100644 src/controller/youporn/youpornGet.ts create mode 100644 src/controller/youporn/youpornGetRelated.ts create mode 100644 src/controller/youporn/youpornRandom.ts create mode 100644 src/controller/youporn/youpornSearch.ts diff --git a/src/controller/pornhub/pornhubGet.ts b/src/controller/pornhub/pornhubGet.ts new file mode 100644 index 0000000..7b23447 --- /dev/null +++ b/src/controller/pornhub/pornhubGet.ts @@ -0,0 +1,55 @@ +import { scrapeContent } from "../../scraper/pornhub/pornhubGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function getPornhub(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + + /** + * @api {get} /pornhub/get?id=:id Get Pornhub + * @apiName Get pornhub + * @apiGroup pornhub + * @apiDescription Get a pornhub video based on id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7 + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7") as resp: + * print(await resp.json()) + */ + + const url = `${c.PORNHUB}/view_video.php?viewkey=${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/pornhub/pornhubGetRelated.ts b/src/controller/pornhub/pornhubGetRelated.ts new file mode 100644 index 0000000..8672f8a --- /dev/null +++ b/src/controller/pornhub/pornhubGetRelated.ts @@ -0,0 +1,55 @@ +import { scrapeContent } from "../../scraper/pornhub/pornhubSearchController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function relatedPornhub(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + + /** + * @api {get} /pornhub/get?id=:id Get Pornhub related videos + * @apiName Get pornhub related videos + * @apiGroup pornhub + * @apiDescription Get a related pornhub videos based on id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7 + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7") as resp: + * print(await resp.json()) + */ + + const url = `${c.PORNHUB}/view_video.php?viewkey=${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/pornhub/pornhubRandom.ts b/src/controller/pornhub/pornhubRandom.ts new file mode 100644 index 0000000..4e3f194 --- /dev/null +++ b/src/controller/pornhub/pornhubRandom.ts @@ -0,0 +1,50 @@ +import { Request, Response } from "express"; +import { scrapeContent } from "../../scraper/pornhub/pornhubGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; + +export async function randomPornhub(req: Request, res: Response) { + try { + /** + * @api {get} /pornhub/random Random pornhub video + * @apiName Random pornhub + * @apiGroup pornhub + * @apiDescription Gets random pornhub video + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/pornhub/random + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/pornhub/random") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/pornhub/random") as resp: + * print(await resp.json()) + * + */ + const url = `${c.PORNHUB}/video/random`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/pornhub/pornhubSearch.ts b/src/controller/pornhub/pornhubSearch.ts new file mode 100644 index 0000000..dba7233 --- /dev/null +++ b/src/controller/pornhub/pornhubSearch.ts @@ -0,0 +1,66 @@ +import { scrapeContent } from "../../scraper/pornhub/pornhubSearchController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError, spacer } from "../../utils/modifier"; +import { Request, Response } from "express"; +const sorting = ["mr", "mv", "tr", "lg"]; + +export async function searchPornhub(req: Request, res: Response) { + try { + /** + * @api {get} /pornhub/search Search pornhub videos + * @apiName Search pornhub + * @apiGroup pornhub + * @apiDescription Search pornhub videos + * @apiParam {String} key Keyword to search + * @apiParam {Number} [page=1] Page number + * @apiParam {String} [sort=mr] Sort by + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/pornhub/search?key=milf + * curl -i https://lust.sinkaroid.org/pornhub/search?key=milf&page=2&sort=mr + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/pornhub/search?key=milf") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/pornhub/search?key=milf") as resp: + * print(await resp.json()) + */ + + const key = req.query.key as string; + const page = req.query.page || 1; + const sort = req.query.sort as string; + if (!key) throw Error("Parameter key is required"); + if (isNaN(Number(page))) throw Error("Parameter page must be a number"); + + let url; + if (!sort) url = `${c.PORNHUB}/video/search?search=${spacer(key)}`; + else if (!sorting.includes(sort)) url = `${c.PORNHUB}/video/search?search=${spacer(key)}&page=${page}`; + + else url = `${c.PORNHUB}/video/search?search=${spacer(key)}&o=${sort}&page=${page}`; + console.log(url); + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} \ No newline at end of file diff --git a/src/controller/redtube/redtubeGet.ts b/src/controller/redtube/redtubeGet.ts new file mode 100644 index 0000000..3638c26 --- /dev/null +++ b/src/controller/redtube/redtubeGet.ts @@ -0,0 +1,56 @@ +import { scrapeContent } from "../../scraper/redtube/redtubeGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function getRedtube(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + if (isNaN(Number(id))) throw Error("Parameter id must be a number"); + + /** + * @api {get} /redtube/get?id=:id Get Redtube + * @apiName Get redtube + * @apiGroup redtube + * @apiDescription Get a redtube video based on id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/redtube/get?id=42763661 + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/redtube/get?id=42763661") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/redtube/get?id=42763661") as resp: + * print(await resp.json()) + */ + + const url = `${c.REDTUBE}/${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/redtube/redtubeGetRelated.ts b/src/controller/redtube/redtubeGetRelated.ts new file mode 100644 index 0000000..5b7b005 --- /dev/null +++ b/src/controller/redtube/redtubeGetRelated.ts @@ -0,0 +1,54 @@ +import { scrapeContent } from "../../scraper/redtube/redtubeSearchController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function relatedRedtube(req: Request, res: Response) { + try { + /** + * @api {get} /redtube/get?id=:id Get redtube related videos + * @apiName Get redtube related videos + * @apiGroup redtube + * @apiDescription Get a related redtube videos based on id + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/redtube/get?id=41698751 + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/redtube/get?id=41698751") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/redtube/get?id=41698751") as resp: + * print(await resp.json()) + */ + + const id = req.query.id as string; + if (!id) throw Error("Parameter key is required"); + if (isNaN(Number(id))) throw Error("Parameter id must be a number"); + + const url = `${c.REDTUBE}/${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} \ No newline at end of file diff --git a/src/controller/redtube/redtubeRandom.ts b/src/controller/redtube/redtubeRandom.ts new file mode 100644 index 0000000..1d6ff14 --- /dev/null +++ b/src/controller/redtube/redtubeRandom.ts @@ -0,0 +1,65 @@ +import { scrapeContent } from "../../scraper/redtube/redtubeGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; +import { load } from "cheerio"; +import LustPress from "../../LustPress"; + +const lust = new LustPress(); + +export async function randomRedtube(req: Request, res: Response) { + try { + + + /** + * @api {get} /redtube/random Get random redtube + * @apiName Get random redtube + * @apiGroup redtube + * @apiDescription Get a random redtube video + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/redtube/random + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/redtube/random") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/redtube/random") as resp: + * print(await resp.json()) + */ + const resolve = await lust.fetchBody(c.REDTUBE); + const $ = load(resolve); + const search = $("a.video_link") + .map((i, el) => { + return $(el).attr("href"); + }).get(); + const random = Math.floor(Math.random() * search.length); + + const url = c.REDTUBE + search[random]; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/redtube/redtubeSearch.ts b/src/controller/redtube/redtubeSearch.ts new file mode 100644 index 0000000..de52927 --- /dev/null +++ b/src/controller/redtube/redtubeSearch.ts @@ -0,0 +1,58 @@ +import { scrapeContent } from "../../scraper/redtube/redtubeSearchController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError, spacer } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function searchRedtube(req: Request, res: Response) { + try { + /** + * @api {get} /redtube/search Search redtube videos + * @apiName Search redtube + * @apiGroup redtube + * @apiDescription Search redtube videos + * @apiParam {String} key Keyword to search + * @apiParam {Number} [page=1] Page number + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/redtube/search?key=milf + * curl -i https://lust.sinkaroid.org/redtube/search?key=milf&page=2 + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/redtube/search?key=milf") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/redtube/search?key=milf") as resp: + * print(await resp.json()) + */ + + const key = req.query.key as string; + const page = req.query.page || 1; + if (!key) throw Error("Parameter key is required"); + if (isNaN(Number(page))) throw Error("Parameter page must be a number"); + + const url = `${c.REDTUBE}/?search=${spacer(key)}&page=${page}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} \ No newline at end of file diff --git a/src/controller/xhamster/xhamsterGet.ts b/src/controller/xhamster/xhamsterGet.ts new file mode 100644 index 0000000..3ff50cf --- /dev/null +++ b/src/controller/xhamster/xhamsterGet.ts @@ -0,0 +1,55 @@ +import { scrapeContent } from "../../scraper/xhamster/xhamsterGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function getXhamster(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + + /** + * @api {get} /xhamster/get?id=:id Get xhamster + * @apiName Get xhamster + * @apiGroup xhamster + * @apiDescription Get a xhamster video based on id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xhamster/get?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xhamster/get?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xhamster/get?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") as resp: + * print(await resp.json()) + */ + + const url = `${c.XHAMSTER}/${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/xhamster/xhamsterGetRelated.ts b/src/controller/xhamster/xhamsterGetRelated.ts new file mode 100644 index 0000000..42e09ac --- /dev/null +++ b/src/controller/xhamster/xhamsterGetRelated.ts @@ -0,0 +1,55 @@ +import { scrapeContent } from "../../scraper/xhamster/xhamsterSearchController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function relatedXhamster(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + + /** + * @api {get} /xhamster/get?id=:id Get related xhamster + * @apiName Get related xhamster + * @apiGroup xhamster + * @apiDescription Get a xhamster video based on related id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xhamster/related?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xhamster/related?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xhamster/related?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") as resp: + * print(await resp.json()) + */ + + const url = `${c.XHAMSTER}/${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/xhamster/xhamsterRandom.ts b/src/controller/xhamster/xhamsterRandom.ts new file mode 100644 index 0000000..981a349 --- /dev/null +++ b/src/controller/xhamster/xhamsterRandom.ts @@ -0,0 +1,63 @@ +import { scrapeContent } from "../../scraper/xhamster/xhamsterGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; +import { load } from "cheerio"; +import LustPress from "../../LustPress"; + +const lust = new LustPress(); + +export async function randomXhamster(req: Request, res: Response) { + try { + + + /** + * @api {get} /xhamster/random Get random xhamster + * @apiName Get random xhamster + * @apiGroup xhamster + * @apiDescription Get a random xhamster video + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xhamster/random + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xhamster/random") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xhamster/random") as resp: + * print(await resp.json()) + */ + const resolve = await lust.fetchBody(`${c.XHAMSTER}/newest`); + const $ = load(resolve); + const search = $("a.root-9d8b4.video-thumb-info__name.role-pop.with-dropdown") + .map((i, el) => $(el).attr("href")) + .get(); + + const search_ = search.map((el) => el.replace(c.XHAMSTER, "")); + const random = Math.floor(Math.random() * search_.length); + const url = c.XHAMSTER + search_[random]; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/xhamster/xhamsterSearch.ts b/src/controller/xhamster/xhamsterSearch.ts new file mode 100644 index 0000000..ad3987a --- /dev/null +++ b/src/controller/xhamster/xhamsterSearch.ts @@ -0,0 +1,58 @@ +import { scrapeContent } from "../../scraper/xhamster/xhamsterSearchController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError, spacer } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function searchXhamster(req: Request, res: Response) { + try { + /** + * @api {get} /xhamster/search Search xhamster videos + * @apiName Search xhamster + * @apiGroup xhamster + * @apiDescription Search xhamster videos + * @apiParam {String} key Keyword to search + * @apiParam {Number} [page=1] Page number + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xhamster/search?key=milf + * curl -i https://lust.sinkaroid.org/xhamster/search?key=milf&page=2 + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xhamster/search?key=milf") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xhamster/search?key=milf") as resp: + * print(await resp.json()) + */ + + const key = req.query.key as string; + const page = req.query.page || 1; + if (!key) throw Error("Parameter key is required"); + if (isNaN(Number(page))) throw Error("Parameter page must be a number"); + + const url = `${c.XHAMSTER}/search/${spacer(key)}?page=${page}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} \ No newline at end of file diff --git a/src/controller/xnxx/xnxxGet.ts b/src/controller/xnxx/xnxxGet.ts new file mode 100644 index 0000000..3bab609 --- /dev/null +++ b/src/controller/xnxx/xnxxGet.ts @@ -0,0 +1,55 @@ +import { scrapeContent } from "../../scraper/xnxx/xnxxGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function getXnxx(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + + /** + * @api {get} /xnxx/get?id=:id Get xnxx + * @apiName Get xnxx + * @apiGroup xnxx + * @apiDescription Get a xnxx video based on id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xnxx/get?id=video-17vah71a/makima_y_denji + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xnxx/get?id=video-17vah71a/makima_y_denji") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xnxx/get?id=video-17vah71a/makima_y_denji") as resp: + * print(await resp.json()) + */ + + const url = `${c.XNXX}/${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/xnxx/xnxxGetRelated.ts b/src/controller/xnxx/xnxxGetRelated.ts new file mode 100644 index 0000000..fe8c080 --- /dev/null +++ b/src/controller/xnxx/xnxxGetRelated.ts @@ -0,0 +1,55 @@ +import { scrapeContent } from "../../scraper/xnxx/xnxxGetRelatedController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function relatedXnxx(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + + /** + * @api {get} /xnxx/get?id=:id Get related xnxx + * @apiName Get related xnxx + * @apiGroup xnxx + * @apiDescription Get a xnxx video based on related id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xnxx/related?id=video-17vah71a/makima_y_denji + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xnxx/related?id=video-17vah71a/makima_y_denji") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xnxx/related?id=video-17vah71a/makima_y_denji") as resp: + * print(await resp.json()) + */ + + const url = `${c.XNXX}/${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/xnxx/xnxxRandom.ts b/src/controller/xnxx/xnxxRandom.ts new file mode 100644 index 0000000..037a846 --- /dev/null +++ b/src/controller/xnxx/xnxxRandom.ts @@ -0,0 +1,63 @@ +import { scrapeContent } from "../../scraper/xnxx/xnxxGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; +import { load } from "cheerio"; +import LustPress from "../../LustPress"; + +const lust = new LustPress(); + +export async function randomXnxx(req: Request, res: Response) { + try { + + + /** + * @api {get} /xnxx/random Get random xnxx + * @apiName Get random xnxx + * @apiGroup xnxx + * @apiDescription Get a random xnxx video + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xnxx/random + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xnxx/random") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xnxx/random") as resp: + * print(await resp.json()) + */ + const resolve = await lust.fetchBody("https://www.xnxx.com/search/random/random"); + const $ = load(resolve); + const search = $("div.mozaique > div") + .map((i, el) => { + return $(el).find("a").attr("href"); + }).get(); + const random = Math.floor(Math.random() * search.length); + + const url = c.XNXX + search[random]; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/xnxx/xnxxSearch.ts b/src/controller/xnxx/xnxxSearch.ts new file mode 100644 index 0000000..3b5319b --- /dev/null +++ b/src/controller/xnxx/xnxxSearch.ts @@ -0,0 +1,58 @@ +import { scrapeContent } from "../../scraper/xnxx/xnxxSearchController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError, spacer } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function searchXnxx(req: Request, res: Response) { + try { + /** + * @api {get} /xnxx/search Search xnxx videos + * @apiName Search xnxx + * @apiGroup xnxx + * @apiDescription Search xnxx videos + * @apiParam {String} key Keyword to search + * @apiParam {Number} [page=0] Page number + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xnxx/search?key=milf + * curl -i https://lust.sinkaroid.org/xnxx/search?key=milf&page=2 + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xnxx/search?key=milf") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xnxx/search?key=milf") as resp: + * print(await resp.json()) + */ + + const key = req.query.key as string; + const page = req.query.page || 0; + if (!key) throw Error("Parameter key is required"); + if (isNaN(Number(page))) throw Error("Parameter page must be a number"); + + const url = `${c.XNXX}/search/${spacer(key)}/${page}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} \ No newline at end of file diff --git a/src/controller/xvideos/xvideosGet.ts b/src/controller/xvideos/xvideosGet.ts new file mode 100644 index 0000000..02e5795 --- /dev/null +++ b/src/controller/xvideos/xvideosGet.ts @@ -0,0 +1,55 @@ +import { scrapeContent } from "../../scraper/xvideos/xvideosGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function getXvideos(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + + /** + * @api {get} /xvideos/get?id=:id Get xvideos + * @apiName Get xvideos + * @apiGroup xvideos + * @apiDescription Get a xvideos video based on id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xvideos/get?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_ + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xvideos/get?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xvideos/get?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") as resp: + * print(await resp.json()) + */ + + const url = `${c.XVIDEOS}/${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/xvideos/xvideosGetRelated.ts b/src/controller/xvideos/xvideosGetRelated.ts new file mode 100644 index 0000000..deb758a --- /dev/null +++ b/src/controller/xvideos/xvideosGetRelated.ts @@ -0,0 +1,55 @@ +import { scrapeContent } from "../../scraper/xvideos/xvideosGetRelatedController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function relatedXvideos(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + + /** + * @api {get} /xvideos/get?id=:id Get related xvideos + * @apiName Get related xvideos + * @apiGroup xvideos + * @apiDescription Get a xvideos video based on related id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xvideos/related?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_ + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xvideos/related?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xvideos/related?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") as resp: + * print(await resp.json()) + */ + + const url = `${c.XVIDEOS}/${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/xvideos/xvideosRandom.ts b/src/controller/xvideos/xvideosRandom.ts new file mode 100644 index 0000000..99d51ce --- /dev/null +++ b/src/controller/xvideos/xvideosRandom.ts @@ -0,0 +1,63 @@ +import { scrapeContent } from "../../scraper/xvideos/xvideosGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; +import { load } from "cheerio"; +import LustPress from "../../LustPress"; + +const lust = new LustPress(); + +export async function randomXvideos(req: Request, res: Response) { + try { + /** + * @api {get} /xvideos/random Get random xvideos + * @apiName Get random xvideos + * @apiGroup xvideos + * @apiDescription Get a random xvideos video + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xvideos/random + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xvideos/random") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xvideos/random") as resp: + * print(await resp.json()) + */ + const resolve = await lust.fetchBody(c.XVIDEOS); + const $ = load(resolve); + const search = $("div.thumb-under") + .find("a") + .map((i, el) => $(el).attr("href")) + .get(); + const filtered = search.filter((el) => el.includes("/video")); + const filtered_ = filtered.filter((el) => !el.includes("THUMBNUM")); + const random = Math.floor(Math.random() * filtered_.length); + + const url = c.XVIDEOS + filtered[random]; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/xvideos/xvideosSearch.ts b/src/controller/xvideos/xvideosSearch.ts new file mode 100644 index 0000000..3a0d0a1 --- /dev/null +++ b/src/controller/xvideos/xvideosSearch.ts @@ -0,0 +1,58 @@ +import { scrapeContent } from "../../scraper/xvideos/xvideosSearchController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError, spacer } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function searchXvideos(req: Request, res: Response) { + try { + /** + * @api {get} /xvideos/search Search xvideos videos + * @apiName Search xvideos + * @apiGroup xvideos + * @apiDescription Search xvideos videos + * @apiParam {String} key Keyword to search + * @apiParam {Number} [page=0] Page number + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/xvideos/search?key=milf + * curl -i https://lust.sinkaroid.org/xvideos/search?key=milf&page=2 + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/xvideos/search?key=milf") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/xvideos/search?key=milf") as resp: + * print(await resp.json()) + */ + + const key = req.query.key as string; + const page = req.query.page || 0; + if (!key) throw Error("Parameter key is required"); + if (isNaN(Number(page))) throw Error("Parameter page must be a number"); + + const url = `${c.XVIDEOS}/?k=${spacer(key)}&p=${page}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} \ No newline at end of file diff --git a/src/controller/youporn/youpornGet.ts b/src/controller/youporn/youpornGet.ts new file mode 100644 index 0000000..14c80aa --- /dev/null +++ b/src/controller/youporn/youpornGet.ts @@ -0,0 +1,55 @@ +import { scrapeContent } from "../../scraper/youporn/youpornGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function getYouporn(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + + /** + * @api {get} /youporn/get?id=:id Get youporn + * @apiName Get youporn + * @apiGroup youporn + * @apiDescription Get a youporn video based on id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/youporn/get?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/youporn/get?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/youporn/get?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") as resp: + * print(await resp.json()) + */ + + const url = `${c.YOUPORN}/watch/${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/youporn/youpornGetRelated.ts b/src/controller/youporn/youpornGetRelated.ts new file mode 100644 index 0000000..2bfaef1 --- /dev/null +++ b/src/controller/youporn/youpornGetRelated.ts @@ -0,0 +1,55 @@ +import { scrapeContent } from "../../scraper/youporn/youpornSearchController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function relatedYouporn(req: Request, res: Response) { + try { + const id = req.query.id as string; + if (!id) throw Error("Parameter id is required"); + + /** + * @api {get} /youporn/get?id=:id Get related youporn + * @apiName Get related youporn + * @apiGroup youporn + * @apiDescription Get a youporn video based on related id + * + * @apiParam {String} id Video ID + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/youporn/related?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/youporn/related?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/youporn/related?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") as resp: + * print(await resp.json()) + */ + + const url = `${c.YOUPORN}/watch/${id}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/youporn/youpornRandom.ts b/src/controller/youporn/youpornRandom.ts new file mode 100644 index 0000000..9f1d49e --- /dev/null +++ b/src/controller/youporn/youpornRandom.ts @@ -0,0 +1,62 @@ +import { scrapeContent } from "../../scraper/youporn/youpornGetController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError } from "../../utils/modifier"; +import { Request, Response } from "express"; +import { load } from "cheerio"; +import LustPress from "../../LustPress"; + +const lust = new LustPress(); + +export async function randomYouporn(req: Request, res: Response) { + try { + + + /** + * @api {get} /youporn/random Get random youporn + * @apiName Get random youporn + * @apiGroup youporn + * @apiDescription Get a random youporn video + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/youporn/random + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/youporn/random") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/youporn/random") as resp: + * print(await resp.json()) + */ + const resolve = await lust.fetchBody(`${c.YOUPORN}`); + const $ = load(resolve); + const search = $("a[href^='/watch/']") + .map((i, el) => { + return $(el).attr("href"); + }).get(); + const random = Math.floor(Math.random() * search.length); + const url = c.YOUPORN + search[random]; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} diff --git a/src/controller/youporn/youpornSearch.ts b/src/controller/youporn/youpornSearch.ts new file mode 100644 index 0000000..6a31082 --- /dev/null +++ b/src/controller/youporn/youpornSearch.ts @@ -0,0 +1,58 @@ +import { scrapeContent } from "../../scraper/youporn/youpornSearchController"; +import c from "../../utils/options"; +import { logger } from "../../utils/logger"; +import { maybeError, spacer } from "../../utils/modifier"; +import { Request, Response } from "express"; + +export async function searchYouporn(req: Request, res: Response) { + try { + /** + * @api {get} /youporn/search Search youporn videos + * @apiName Search youporn + * @apiGroup youporn + * @apiDescription Search youporn videos + * @apiParam {String} key Keyword to search + * @apiParam {Number} [page=1] Page number + * + * @apiSuccessExample {json} Success-Response: + * HTTP/1.1 200 OK + * HTTP/1.1 400 Bad Request + * + * @apiExample {curl} curl + * curl -i https://lust.sinkaroid.org/youporn/search?key=milf + * curl -i https://lust.sinkaroid.org/youporn/search?key=milf&page=2 + * + * @apiExample {js} JS/TS + * import axios from "axios" + * + * axios.get("https://lust.sinkaroid.org/youporn/search?key=milf") + * .then(res => console.log(res.data)) + * .catch(err => console.error(err)) + * + * @apiExample {python} Python + * import aiohttp + * async with aiohttp.ClientSession() as session: + * async with session.get("https://lust.sinkaroid.org/youporn/search?key=milf") as resp: + * print(await resp.json()) + */ + + const key = req.query.key as string; + const page = req.query.page || 1; + if (!key) throw Error("Parameter key is required"); + if (isNaN(Number(page))) throw Error("Parameter page must be a number"); + + const url = `${c.YOUPORN}/search/?query=${spacer(key)}&page=${page}`; + const data = await scrapeContent(url); + logger.info({ + path: req.path, + query: req.query, + method: req.method, + ip: req.ip, + useragent: req.get("User-Agent") + }); + return res.json(data); + } catch (err) { + const e = err as Error; + res.status(400).json(maybeError(false, e.message)); + } +} \ No newline at end of file From 5cf38dcdf0ff3717ae9bd8799c13a46be56378f5 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:27:35 +0700 Subject: [PATCH 16/17] refactor(controller): change sinkaroid.org => scathach.id docs types --- src/controller/pornhub/pornhubGet.ts | 6 +++--- src/controller/pornhub/pornhubGetRelated.ts | 6 +++--- src/controller/pornhub/pornhubRandom.ts | 6 +++--- src/controller/pornhub/pornhubSearch.ts | 8 ++++---- src/controller/redtube/redtubeGet.ts | 6 +++--- src/controller/redtube/redtubeGetRelated.ts | 6 +++--- src/controller/redtube/redtubeRandom.ts | 6 +++--- src/controller/redtube/redtubeSearch.ts | 8 ++++---- src/controller/xhamster/xhamsterGet.ts | 6 +++--- src/controller/xhamster/xhamsterGetRelated.ts | 6 +++--- src/controller/xhamster/xhamsterRandom.ts | 6 +++--- src/controller/xhamster/xhamsterSearch.ts | 8 ++++---- src/controller/xnxx/xnxxGet.ts | 6 +++--- src/controller/xnxx/xnxxGetRelated.ts | 6 +++--- src/controller/xnxx/xnxxRandom.ts | 6 +++--- src/controller/xnxx/xnxxSearch.ts | 8 ++++---- src/controller/xvideos/xvideosGet.ts | 6 +++--- src/controller/xvideos/xvideosGetRelated.ts | 6 +++--- src/controller/xvideos/xvideosRandom.ts | 6 +++--- src/controller/xvideos/xvideosSearch.ts | 8 ++++---- src/controller/youporn/youpornGet.ts | 6 +++--- src/controller/youporn/youpornGetRelated.ts | 6 +++--- src/controller/youporn/youpornRandom.ts | 6 +++--- src/controller/youporn/youpornSearch.ts | 8 ++++---- 24 files changed, 78 insertions(+), 78 deletions(-) diff --git a/src/controller/pornhub/pornhubGet.ts b/src/controller/pornhub/pornhubGet.ts index 7b23447..f1546f5 100644 --- a/src/controller/pornhub/pornhubGet.ts +++ b/src/controller/pornhub/pornhubGet.ts @@ -22,19 +22,19 @@ export async function getPornhub(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7 + * curl -i https://lust.scathach.id/pornhub/get?id=ph63c4e1dc48fe7 * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7") + * axios.get("https://lust.scathach.id/pornhub/get?id=ph63c4e1dc48fe7") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7") as resp: + * async with session.get("https://lust.scathach.id/pornhub/get?id=ph63c4e1dc48fe7") as resp: * print(await resp.json()) */ diff --git a/src/controller/pornhub/pornhubGetRelated.ts b/src/controller/pornhub/pornhubGetRelated.ts index 8672f8a..92e9aac 100644 --- a/src/controller/pornhub/pornhubGetRelated.ts +++ b/src/controller/pornhub/pornhubGetRelated.ts @@ -22,19 +22,19 @@ export async function relatedPornhub(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7 + * curl -i https://lust.scathach.id/pornhub/get?id=ph63c4e1dc48fe7 * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7") + * axios.get("https://lust.scathach.id/pornhub/get?id=ph63c4e1dc48fe7") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/pornhub/get?id=ph63c4e1dc48fe7") as resp: + * async with session.get("https://lust.scathach.id/pornhub/get?id=ph63c4e1dc48fe7") as resp: * print(await resp.json()) */ diff --git a/src/controller/pornhub/pornhubRandom.ts b/src/controller/pornhub/pornhubRandom.ts index 4e3f194..2c6ef99 100644 --- a/src/controller/pornhub/pornhubRandom.ts +++ b/src/controller/pornhub/pornhubRandom.ts @@ -17,19 +17,19 @@ export async function randomPornhub(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/pornhub/random + * curl -i https://lust.scathach.id/pornhub/random * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/pornhub/random") + * axios.get("https://lust.scathach.id/pornhub/random") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/pornhub/random") as resp: + * async with session.get("https://lust.scathach.id/pornhub/random") as resp: * print(await resp.json()) * */ diff --git a/src/controller/pornhub/pornhubSearch.ts b/src/controller/pornhub/pornhubSearch.ts index dba7233..a706428 100644 --- a/src/controller/pornhub/pornhubSearch.ts +++ b/src/controller/pornhub/pornhubSearch.ts @@ -21,20 +21,20 @@ export async function searchPornhub(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/pornhub/search?key=milf - * curl -i https://lust.sinkaroid.org/pornhub/search?key=milf&page=2&sort=mr + * curl -i https://lust.scathach.id/pornhub/search?key=milf + * curl -i https://lust.scathach.id/pornhub/search?key=milf&page=2&sort=mr * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/pornhub/search?key=milf") + * axios.get("https://lust.scathach.id/pornhub/search?key=milf") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/pornhub/search?key=milf") as resp: + * async with session.get("https://lust.scathach.id/pornhub/search?key=milf") as resp: * print(await resp.json()) */ diff --git a/src/controller/redtube/redtubeGet.ts b/src/controller/redtube/redtubeGet.ts index 3638c26..61d47db 100644 --- a/src/controller/redtube/redtubeGet.ts +++ b/src/controller/redtube/redtubeGet.ts @@ -23,19 +23,19 @@ export async function getRedtube(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/redtube/get?id=42763661 + * curl -i https://lust.scathach.id/redtube/get?id=42763661 * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/redtube/get?id=42763661") + * axios.get("https://lust.scathach.id/redtube/get?id=42763661") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/redtube/get?id=42763661") as resp: + * async with session.get("https://lust.scathach.id/redtube/get?id=42763661") as resp: * print(await resp.json()) */ diff --git a/src/controller/redtube/redtubeGetRelated.ts b/src/controller/redtube/redtubeGetRelated.ts index 5b7b005..8865a75 100644 --- a/src/controller/redtube/redtubeGetRelated.ts +++ b/src/controller/redtube/redtubeGetRelated.ts @@ -17,19 +17,19 @@ export async function relatedRedtube(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/redtube/get?id=41698751 + * curl -i https://lust.scathach.id/redtube/get?id=41698751 * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/redtube/get?id=41698751") + * axios.get("https://lust.scathach.id/redtube/get?id=41698751") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/redtube/get?id=41698751") as resp: + * async with session.get("https://lust.scathach.id/redtube/get?id=41698751") as resp: * print(await resp.json()) */ diff --git a/src/controller/redtube/redtubeRandom.ts b/src/controller/redtube/redtubeRandom.ts index 1d6ff14..3dd6257 100644 --- a/src/controller/redtube/redtubeRandom.ts +++ b/src/controller/redtube/redtubeRandom.ts @@ -25,19 +25,19 @@ export async function randomRedtube(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/redtube/random + * curl -i https://lust.scathach.id/redtube/random * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/redtube/random") + * axios.get("https://lust.scathach.id/redtube/random") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/redtube/random") as resp: + * async with session.get("https://lust.scathach.id/redtube/random") as resp: * print(await resp.json()) */ const resolve = await lust.fetchBody(c.REDTUBE); diff --git a/src/controller/redtube/redtubeSearch.ts b/src/controller/redtube/redtubeSearch.ts index de52927..afaf7ca 100644 --- a/src/controller/redtube/redtubeSearch.ts +++ b/src/controller/redtube/redtubeSearch.ts @@ -19,20 +19,20 @@ export async function searchRedtube(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/redtube/search?key=milf - * curl -i https://lust.sinkaroid.org/redtube/search?key=milf&page=2 + * curl -i https://lust.scathach.id/redtube/search?key=milf + * curl -i https://lust.scathach.id/redtube/search?key=milf&page=2 * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/redtube/search?key=milf") + * axios.get("https://lust.scathach.id/redtube/search?key=milf") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/redtube/search?key=milf") as resp: + * async with session.get("https://lust.scathach.id/redtube/search?key=milf") as resp: * print(await resp.json()) */ diff --git a/src/controller/xhamster/xhamsterGet.ts b/src/controller/xhamster/xhamsterGet.ts index 3ff50cf..981b67a 100644 --- a/src/controller/xhamster/xhamsterGet.ts +++ b/src/controller/xhamster/xhamsterGet.ts @@ -22,19 +22,19 @@ export async function getXhamster(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xhamster/get?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx + * curl -i https://lust.scathach.id/xhamster/get?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xhamster/get?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") + * axios.get("https://lust.scathach.id/xhamster/get?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xhamster/get?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") as resp: + * async with session.get("https://lust.scathach.id/xhamster/get?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") as resp: * print(await resp.json()) */ diff --git a/src/controller/xhamster/xhamsterGetRelated.ts b/src/controller/xhamster/xhamsterGetRelated.ts index 42e09ac..7f88e44 100644 --- a/src/controller/xhamster/xhamsterGetRelated.ts +++ b/src/controller/xhamster/xhamsterGetRelated.ts @@ -22,19 +22,19 @@ export async function relatedXhamster(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xhamster/related?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx + * curl -i https://lust.scathach.id/xhamster/related?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xhamster/related?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") + * axios.get("https://lust.scathach.id/xhamster/related?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xhamster/related?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") as resp: + * async with session.get("https://lust.scathach.id/xhamster/related?id=videos/horny-makima-tests-new-toy-and-cums-intensely-xhAa5wx") as resp: * print(await resp.json()) */ diff --git a/src/controller/xhamster/xhamsterRandom.ts b/src/controller/xhamster/xhamsterRandom.ts index 981a349..b2dd4ae 100644 --- a/src/controller/xhamster/xhamsterRandom.ts +++ b/src/controller/xhamster/xhamsterRandom.ts @@ -23,19 +23,19 @@ export async function randomXhamster(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xhamster/random + * curl -i https://lust.scathach.id/xhamster/random * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xhamster/random") + * axios.get("https://lust.scathach.id/xhamster/random") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xhamster/random") as resp: + * async with session.get("https://lust.scathach.id/xhamster/random") as resp: * print(await resp.json()) */ const resolve = await lust.fetchBody(`${c.XHAMSTER}/newest`); diff --git a/src/controller/xhamster/xhamsterSearch.ts b/src/controller/xhamster/xhamsterSearch.ts index ad3987a..5590546 100644 --- a/src/controller/xhamster/xhamsterSearch.ts +++ b/src/controller/xhamster/xhamsterSearch.ts @@ -19,20 +19,20 @@ export async function searchXhamster(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xhamster/search?key=milf - * curl -i https://lust.sinkaroid.org/xhamster/search?key=milf&page=2 + * curl -i https://lust.scathach.id/xhamster/search?key=milf + * curl -i https://lust.scathach.id/xhamster/search?key=milf&page=2 * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xhamster/search?key=milf") + * axios.get("https://lust.scathach.id/xhamster/search?key=milf") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xhamster/search?key=milf") as resp: + * async with session.get("https://lust.scathach.id/xhamster/search?key=milf") as resp: * print(await resp.json()) */ diff --git a/src/controller/xnxx/xnxxGet.ts b/src/controller/xnxx/xnxxGet.ts index 3bab609..fa0a798 100644 --- a/src/controller/xnxx/xnxxGet.ts +++ b/src/controller/xnxx/xnxxGet.ts @@ -22,19 +22,19 @@ export async function getXnxx(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xnxx/get?id=video-17vah71a/makima_y_denji + * curl -i https://lust.scathach.id/xnxx/get?id=video-17vah71a/makima_y_denji * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xnxx/get?id=video-17vah71a/makima_y_denji") + * axios.get("https://lust.scathach.id/xnxx/get?id=video-17vah71a/makima_y_denji") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xnxx/get?id=video-17vah71a/makima_y_denji") as resp: + * async with session.get("https://lust.scathach.id/xnxx/get?id=video-17vah71a/makima_y_denji") as resp: * print(await resp.json()) */ diff --git a/src/controller/xnxx/xnxxGetRelated.ts b/src/controller/xnxx/xnxxGetRelated.ts index fe8c080..4fc270b 100644 --- a/src/controller/xnxx/xnxxGetRelated.ts +++ b/src/controller/xnxx/xnxxGetRelated.ts @@ -22,19 +22,19 @@ export async function relatedXnxx(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xnxx/related?id=video-17vah71a/makima_y_denji + * curl -i https://lust.scathach.id/xnxx/related?id=video-17vah71a/makima_y_denji * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xnxx/related?id=video-17vah71a/makima_y_denji") + * axios.get("https://lust.scathach.id/xnxx/related?id=video-17vah71a/makima_y_denji") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xnxx/related?id=video-17vah71a/makima_y_denji") as resp: + * async with session.get("https://lust.scathach.id/xnxx/related?id=video-17vah71a/makima_y_denji") as resp: * print(await resp.json()) */ diff --git a/src/controller/xnxx/xnxxRandom.ts b/src/controller/xnxx/xnxxRandom.ts index 037a846..74a06cb 100644 --- a/src/controller/xnxx/xnxxRandom.ts +++ b/src/controller/xnxx/xnxxRandom.ts @@ -23,19 +23,19 @@ export async function randomXnxx(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xnxx/random + * curl -i https://lust.scathach.id/xnxx/random * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xnxx/random") + * axios.get("https://lust.scathach.id/xnxx/random") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xnxx/random") as resp: + * async with session.get("https://lust.scathach.id/xnxx/random") as resp: * print(await resp.json()) */ const resolve = await lust.fetchBody("https://www.xnxx.com/search/random/random"); diff --git a/src/controller/xnxx/xnxxSearch.ts b/src/controller/xnxx/xnxxSearch.ts index 3b5319b..49416f1 100644 --- a/src/controller/xnxx/xnxxSearch.ts +++ b/src/controller/xnxx/xnxxSearch.ts @@ -19,20 +19,20 @@ export async function searchXnxx(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xnxx/search?key=milf - * curl -i https://lust.sinkaroid.org/xnxx/search?key=milf&page=2 + * curl -i https://lust.scathach.id/xnxx/search?key=milf + * curl -i https://lust.scathach.id/xnxx/search?key=milf&page=2 * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xnxx/search?key=milf") + * axios.get("https://lust.scathach.id/xnxx/search?key=milf") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xnxx/search?key=milf") as resp: + * async with session.get("https://lust.scathach.id/xnxx/search?key=milf") as resp: * print(await resp.json()) */ diff --git a/src/controller/xvideos/xvideosGet.ts b/src/controller/xvideos/xvideosGet.ts index 02e5795..80688b4 100644 --- a/src/controller/xvideos/xvideosGet.ts +++ b/src/controller/xvideos/xvideosGet.ts @@ -22,19 +22,19 @@ export async function getXvideos(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xvideos/get?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_ + * curl -i https://lust.scathach.id/xvideos/get?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_ * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xvideos/get?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") + * axios.get("https://lust.scathach.id/xvideos/get?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xvideos/get?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") as resp: + * async with session.get("https://lust.scathach.id/xvideos/get?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") as resp: * print(await resp.json()) */ diff --git a/src/controller/xvideos/xvideosGetRelated.ts b/src/controller/xvideos/xvideosGetRelated.ts index deb758a..7e9400a 100644 --- a/src/controller/xvideos/xvideosGetRelated.ts +++ b/src/controller/xvideos/xvideosGetRelated.ts @@ -22,19 +22,19 @@ export async function relatedXvideos(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xvideos/related?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_ + * curl -i https://lust.scathach.id/xvideos/related?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_ * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xvideos/related?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") + * axios.get("https://lust.scathach.id/xvideos/related?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xvideos/related?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") as resp: + * async with session.get("https://lust.scathach.id/xvideos/related?id=video73564387/cute_hentai_maid_with_pink_hair_fucking_uncensored_") as resp: * print(await resp.json()) */ diff --git a/src/controller/xvideos/xvideosRandom.ts b/src/controller/xvideos/xvideosRandom.ts index 99d51ce..8acc3db 100644 --- a/src/controller/xvideos/xvideosRandom.ts +++ b/src/controller/xvideos/xvideosRandom.ts @@ -21,19 +21,19 @@ export async function randomXvideos(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xvideos/random + * curl -i https://lust.scathach.id/xvideos/random * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xvideos/random") + * axios.get("https://lust.scathach.id/xvideos/random") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xvideos/random") as resp: + * async with session.get("https://lust.scathach.id/xvideos/random") as resp: * print(await resp.json()) */ const resolve = await lust.fetchBody(c.XVIDEOS); diff --git a/src/controller/xvideos/xvideosSearch.ts b/src/controller/xvideos/xvideosSearch.ts index 3a0d0a1..728eb9b 100644 --- a/src/controller/xvideos/xvideosSearch.ts +++ b/src/controller/xvideos/xvideosSearch.ts @@ -19,20 +19,20 @@ export async function searchXvideos(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/xvideos/search?key=milf - * curl -i https://lust.sinkaroid.org/xvideos/search?key=milf&page=2 + * curl -i https://lust.scathach.id/xvideos/search?key=milf + * curl -i https://lust.scathach.id/xvideos/search?key=milf&page=2 * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/xvideos/search?key=milf") + * axios.get("https://lust.scathach.id/xvideos/search?key=milf") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/xvideos/search?key=milf") as resp: + * async with session.get("https://lust.scathach.id/xvideos/search?key=milf") as resp: * print(await resp.json()) */ diff --git a/src/controller/youporn/youpornGet.ts b/src/controller/youporn/youpornGet.ts index 14c80aa..92e331d 100644 --- a/src/controller/youporn/youpornGet.ts +++ b/src/controller/youporn/youpornGet.ts @@ -22,19 +22,19 @@ export async function getYouporn(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/youporn/get?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps + * curl -i https://lust.scathach.id/youporn/get?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/youporn/get?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") + * axios.get("https://lust.scathach.id/youporn/get?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/youporn/get?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") as resp: + * async with session.get("https://lust.scathach.id/youporn/get?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") as resp: * print(await resp.json()) */ diff --git a/src/controller/youporn/youpornGetRelated.ts b/src/controller/youporn/youpornGetRelated.ts index 2bfaef1..007f205 100644 --- a/src/controller/youporn/youpornGetRelated.ts +++ b/src/controller/youporn/youpornGetRelated.ts @@ -22,19 +22,19 @@ export async function relatedYouporn(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/youporn/related?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps + * curl -i https://lust.scathach.id/youporn/related?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/youporn/related?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") + * axios.get("https://lust.scathach.id/youporn/related?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/youporn/related?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") as resp: + * async with session.get("https://lust.scathach.id/youporn/related?id=16621192/chainsaw-man-fuck-makima-3d-porn-60-fps") as resp: * print(await resp.json()) */ diff --git a/src/controller/youporn/youpornRandom.ts b/src/controller/youporn/youpornRandom.ts index 9f1d49e..e72e68a 100644 --- a/src/controller/youporn/youpornRandom.ts +++ b/src/controller/youporn/youpornRandom.ts @@ -23,19 +23,19 @@ export async function randomYouporn(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/youporn/random + * curl -i https://lust.scathach.id/youporn/random * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/youporn/random") + * axios.get("https://lust.scathach.id/youporn/random") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/youporn/random") as resp: + * async with session.get("https://lust.scathach.id/youporn/random") as resp: * print(await resp.json()) */ const resolve = await lust.fetchBody(`${c.YOUPORN}`); diff --git a/src/controller/youporn/youpornSearch.ts b/src/controller/youporn/youpornSearch.ts index 6a31082..e0d3014 100644 --- a/src/controller/youporn/youpornSearch.ts +++ b/src/controller/youporn/youpornSearch.ts @@ -19,20 +19,20 @@ export async function searchYouporn(req: Request, res: Response) { * HTTP/1.1 400 Bad Request * * @apiExample {curl} curl - * curl -i https://lust.sinkaroid.org/youporn/search?key=milf - * curl -i https://lust.sinkaroid.org/youporn/search?key=milf&page=2 + * curl -i https://lust.scathach.id/youporn/search?key=milf + * curl -i https://lust.scathach.id/youporn/search?key=milf&page=2 * * @apiExample {js} JS/TS * import axios from "axios" * - * axios.get("https://lust.sinkaroid.org/youporn/search?key=milf") + * axios.get("https://lust.scathach.id/youporn/search?key=milf") * .then(res => console.log(res.data)) * .catch(err => console.error(err)) * * @apiExample {python} Python * import aiohttp * async with aiohttp.ClientSession() as session: - * async with session.get("https://lust.sinkaroid.org/youporn/search?key=milf") as resp: + * async with session.get("https://lust.scathach.id/youporn/search?key=milf") as resp: * print(await resp.json()) */ From 759c79c266a92c504f93e105583778d8eaba18f9 Mon Sep 17 00:00:00 2001 From: sinkaroid Date: Tue, 18 Apr 2023 11:29:19 +0700 Subject: [PATCH 17/17] feat(scraper): add each scraper and its parser flow --- src/scraper/pornhub/pornhubGetController.ts | 78 ++++++++++++++ .../pornhub/pornhubSearchController.ts | 59 ++++++++++ src/scraper/redtube/redtubeGetController.ts | 79 ++++++++++++++ .../redtube/redtubeSearchController.ts | 72 +++++++++++++ src/scraper/xhamster/xhamsterGetController.ts | 83 ++++++++++++++ .../xhamster/xhamsterSearchController.ts | 56 ++++++++++ src/scraper/xnxx/xnxxGetController.ts | 102 ++++++++++++++++++ src/scraper/xnxx/xnxxGetRelatedController.ts | 55 ++++++++++ src/scraper/xnxx/xnxxSearchController.ts | 49 +++++++++ src/scraper/xvideos/xvideosGetController.ts | 92 ++++++++++++++++ .../xvideos/xvideosGetRelatedController.ts | 54 ++++++++++ .../xvideos/xvideosSearchController.ts | 66 ++++++++++++ src/scraper/youporn/youpornGetController.ts | 73 +++++++++++++ .../youporn/youpornSearchController.ts | 53 +++++++++ 14 files changed, 971 insertions(+) create mode 100644 src/scraper/pornhub/pornhubGetController.ts create mode 100644 src/scraper/pornhub/pornhubSearchController.ts create mode 100644 src/scraper/redtube/redtubeGetController.ts create mode 100644 src/scraper/redtube/redtubeSearchController.ts create mode 100644 src/scraper/xhamster/xhamsterGetController.ts create mode 100644 src/scraper/xhamster/xhamsterSearchController.ts create mode 100644 src/scraper/xnxx/xnxxGetController.ts create mode 100644 src/scraper/xnxx/xnxxGetRelatedController.ts create mode 100644 src/scraper/xnxx/xnxxSearchController.ts create mode 100644 src/scraper/xvideos/xvideosGetController.ts create mode 100644 src/scraper/xvideos/xvideosGetRelatedController.ts create mode 100644 src/scraper/xvideos/xvideosSearchController.ts create mode 100644 src/scraper/youporn/youpornGetController.ts create mode 100644 src/scraper/youporn/youpornSearchController.ts diff --git a/src/scraper/pornhub/pornhubGetController.ts b/src/scraper/pornhub/pornhubGetController.ts new file mode 100644 index 0000000..14d5248 --- /dev/null +++ b/src/scraper/pornhub/pornhubGetController.ts @@ -0,0 +1,78 @@ +import { load } from "cheerio"; +import LustPress from "../../LustPress"; +import { IVideoData } from "../../interfaces"; + +const lust = new LustPress(); + +export async function scrapeContent(url: string) { + try { + const resolve = await lust.fetchBody(url); + const $ = load(resolve); + + class PornHub { + link: string; + id: string; + title: string; + image: string; + duration: string; + views: string; + rating: string; + videoInfo: string; + upVote: string; + downVote: string; + video: string; + tags: string[]; + models: string[]; + constructor() { + this.link = $("link[rel='canonical']").attr("href") || "None"; + this.id = this.link.split("=")[1] || "None"; + this.title = $("meta[property='og:title']").attr("content") || "None"; + this.image = $("meta[property='og:image']").attr("content") || "None"; + //get span.count").text() || "None"; + this.rating = $("div.ratingPercent > span.percent").text() || "None"; + this.videoInfo = $("div.videoInfo").text() || "None"; + this.upVote = $("span.votesUp").attr("data-rating") || "None"; + this.downVote = $("span.votesDown").attr("data-rating") || "None"; + this.video = $("meta[property='og:video:url']").attr("content") || "None"; + this.tags = $("div.video-info-row") + .find("a") + .map((i, el) => { + return $(el).text(); + }).get(); + this.tags.shift(); + this.tags = this.tags.map((el) => lust.removeHtmlTagWithoutSpace(el)); + this.models = $("div.pornstarsWrapper.js-pornstarsWrapper") + .find("a") + .map((i, el) => { + return $(el).attr("data-mxptext"); + }).get(); + } + } + + const ph = new PornHub(); + const data: IVideoData = { + success: true, + data: { + title: lust.removeHtmlTagWithoutSpace(ph.title), + id: ph.id, + image: ph.image, + duration: lust.secondToMinute(Number(ph.duration)), + views: ph.views, + rating: ph.rating, + uploaded: ph.videoInfo, + upvoted: ph.upVote, + downvoted: ph.downVote, + models: ph.models, + tags: ph.tags.filter((el) => el !== "Suggest" && el !== " Suggest") + }, + source: ph.link, + assets: [ph.video, ph.image] + }; + return data; + } catch (err) { + const e = err as Error; + throw Error(e.message); + } +} \ No newline at end of file diff --git a/src/scraper/pornhub/pornhubSearchController.ts b/src/scraper/pornhub/pornhubSearchController.ts new file mode 100644 index 0000000..a95a045 --- /dev/null +++ b/src/scraper/pornhub/pornhubSearchController.ts @@ -0,0 +1,59 @@ +import { load } from "cheerio"; +import LustPress from "../../LustPress"; +import c from "../../utils/options"; +import { ISearchVideoData } from "../../interfaces"; + +const lust = new LustPress(); + +export async function scrapeContent(url: string) { + try { + const res = await lust.fetchBody(url); + const $ = load(res); + + class PornhubSearch { + search: object[]; + data: object; + constructor() { + this.search = $("div.wrap") + .map((i, el) => { + const link = $(el).find("a").attr("href"); + const id = link?.split("=")[1]; + const title = $(el).find("a").attr("title"); + const image = $(el).find("img").attr("src"); + const duration = $(el).find("var.duration").text(); + const views = $(el).find("div.videoDetailsBlock").find("span.views").text(); + return { + link: `${c.PORNHUB}${link}`, + id: id, + title: title, + image: image, + duration: duration, + views: views, + video: `${c.PORNHUB}/embed/${id}`, + }; + }).get(); + + this.data = this.search.filter((el: any) => { + return el.link.includes("javascript:void(0)") === false && el.image?.startsWith("data:image") === false; + }); + } + + } + + const ph = new PornhubSearch(); + if (ph.search.length === 0) throw Error("No result found"); + const data = ph.data as string[]; + const result: ISearchVideoData = { + success: true, + data: data, + source: url, + }; + return result; + + + + } catch (err) { + const e = err as Error; + throw Error(e.message); + } +} \ No newline at end of file diff --git a/src/scraper/redtube/redtubeGetController.ts b/src/scraper/redtube/redtubeGetController.ts new file mode 100644 index 0000000..0a2cbcb --- /dev/null +++ b/src/scraper/redtube/redtubeGetController.ts @@ -0,0 +1,79 @@ +import { load } from "cheerio"; +import LustPress from "../../LustPress"; +import { IVideoData } from "../../interfaces"; + +const lust = new LustPress(); + +export async function scrapeContent(url: string) { + try { + const resolve = await lust.fetchBody(url); + const $ = load(resolve); + + class RedTube { + link: string; + id: string; + title: string; + image: string; + duration: string; + views: string; + rating: string; + publish: string; + upVote: string; + downVote: null; + video: string; + tags: string[]; + models: string[]; + constructor() { + this.link = $("link[rel='canonical']").attr("href") || "None"; + this.id = this.link.split("/")[3] || "None"; + this.title = $("meta[property='og:title']").attr("content") || "None"; + this.image = $("meta[property='og:image']").attr("content") || "None"; + this.duration = $("meta[property='og:video:duration']").attr("content") || "0"; + this.views = $("span.video_view_count").text() || "None"; + this.rating = $("div.rating_percent.js_rating_percent").attr("data-percent") + "%" || "None"; + this.publish = $("span.video-infobox-date-added").text().replace("Published on ", "") || "None"; + this.upVote = this.rating; + this.downVote = null; + this.video = $("meta[name='twitter:player']").attr("content") || "None"; + this.tags = $("a.item.video_carousel_item.video_carousel_category, a.item.video_carousel_item.video_carousel_tag") + .map((i, el) => { + return $(el).text(); + }).get(); + this.tags = this.tags.map((el) => lust.removeHtmlTagWithoutSpace(el)); + this.models = $("div.pornstar-name.pornstarPopupWrapper") + .find("a") + .map((i, el) => { + return $(el).text(); + } + ).get(); + this.models = this.models.map((el) => lust.removeHtmlTagWithoutSpace(el)); + this.models = this.models.filter((el) => !el.includes("Subscribe") && !el.includes("Rank")) + .filter((el, i, arr) => arr.indexOf(el) === i); + } + } + + const red = new RedTube(); + const data: IVideoData = { + success: true, + data: { + title: lust.removeHtmlTagWithoutSpace(red.title), + id: red.id, + image: red.image, + duration: lust.secondToMinute(Number(red.duration)), + views: red.views, + rating: red.rating, + uploaded: red.publish, + upvoted: red.upVote, + downvoted: red.downVote, + models: red.models, + tags: red.tags + }, + source: red.link, + assets: [red.video, red.image] + }; + return data; + } catch (err) { + const e = err as Error; + throw Error(e.message); + } +} \ No newline at end of file diff --git a/src/scraper/redtube/redtubeSearchController.ts b/src/scraper/redtube/redtubeSearchController.ts new file mode 100644 index 0000000..f05c677 --- /dev/null +++ b/src/scraper/redtube/redtubeSearchController.ts @@ -0,0 +1,72 @@ +import { load } from "cheerio"; +import LustPress from "../../LustPress"; +import c from "../../utils/options"; +import { ISearchVideoData } from "../../interfaces"; + +const lust = new LustPress(); + +export async function scrapeContent(url: string) { + try { + const res = await lust.fetchBody(url); + const $ = load(res); + + class RedTubeSearch { + views: string[]; + search: object[]; + data: object; + constructor() { + this.views = $("span.video_count") + .map((i, el) => { + const views = $(el).text(); + return views; + }).get(); + this.search = $("a.video_link") + .map((i, el) => { + const link = $(el).attr("href"); + const id = link?.split("/")[1]; + const title = $(el).find("img").attr("alt"); + const image = $(el).find("img").attr("data-src"); + const duration = $(el).find("span.duration").text().split(" ").map((el: string) => { + return el.replace(/[^0-9:]/g, ""); + }).filter((el: string) => { + return el.includes(":"); + }).join(" "); + + return { + link: `${c.REDTUBE}${link}`, + id: id, + title: title, + image: image, + duration: duration, + views: this.views[i], + video: `https://embed.redtube.com/?id=${id}`, + + }; + }).get(); + + + + + this.data = this.search.filter((el: any) => { + return el.link.includes("javascript:void(0)") === false && el.image?.startsWith("data:image") === false; + }); + } + + } + + const red = new RedTubeSearch(); + + if (red.search.length === 0) throw Error("No result found"); + const data = red.data as string[]; + const result: ISearchVideoData = { + success: true, + data: data, + source: url, + }; + return result; + + } catch (err) { + const e = err as Error; + throw Error(e.message); + } +} \ No newline at end of file diff --git a/src/scraper/xhamster/xhamsterGetController.ts b/src/scraper/xhamster/xhamsterGetController.ts new file mode 100644 index 0000000..7e73ac5 --- /dev/null +++ b/src/scraper/xhamster/xhamsterGetController.ts @@ -0,0 +1,83 @@ +import { load } from "cheerio"; +import LustPress from "../../LustPress"; +import { IVideoData } from "../../interfaces"; + +const lust = new LustPress(); + +export async function scrapeContent(url: string) { + try { + const resolve = await lust.fetchBody(url); + const $ = load(resolve); + + class Xhamster { + link: string; + id: string; + title: string; + image: string; + duration: any; + views: string; + rating: string; + publish: string; + upVote: string; + downVote: string; + video: string; + tags: string[]; + models: string[]; + constructor() { + this.link = $("link[rel='canonical']").attr("href") || "None"; + this.id = this.link.split("/")[3] + "/" + this.link.split("/")[4] || "None"; + this.title = $("meta[property='og:title']").attr("content") || "None"; + this.image = $("meta[property='og:image']").attr("content") || "None"; + this.duration = $("script#initials-script").html() || "None"; + //remove window.initials={ and }; + this.duration = this.duration.replace("window.initials=", ""); + this.duration = this.duration.replace(/;/g, ""); + this.duration = JSON.parse(this.duration); + this.duration = this.duration.videoModel.duration || "None"; + this.views = $("div.header-icons").find("span").first().text() || "None"; + this.rating = $("div.header-icons").find("span").eq(1).text() || "None"; + this.publish = $("div.entity-info-container__date").attr("data-tooltip") || "None"; + this.upVote = $("div.rb-new__info").text().split("/")[0].trim() || "None"; + this.downVote = $("div.rb-new__info").text().split("/")[1].trim() || "None"; + this.video = "https://xheve2.com/embed/" + this.link.split("-").pop() || "None"; + this.tags = $("a.video-tag") + .map((i, el) => { + return $(el).text(); + }).get(); + this.tags = this.tags.map((el) => lust.removeHtmlTagWithoutSpace(el)); + this.models = $("a.video-tag") + .map((i, el) => { + return $(el).attr("href"); + } + ).get(); + this.models = this.models.filter((el) => el.startsWith("https://xheve2.com/pornstars/")); + this.models = this.models.map((el) => el.replace("https://xheve2.com/pornstars/", "")); + } + } + + const xh = new Xhamster(); + const data: IVideoData = { + success: true, + data: { + title: lust.removeHtmlTagWithoutSpace(xh.title), + id: xh.id, + image: xh.image, + duration: lust.secondToMinute(Number(xh.duration)), + views: xh.views, + rating: xh.rating, + uploaded: xh.publish, + upvoted: xh.upVote, + downvoted: xh.downVote, + models: xh.models, + tags: xh.tags + }, + source: xh.link, + assets: [xh.video, xh.image] + }; + return data; + + } catch (err) { + const e = err as Error; + throw Error(e.message); + } +} \ No newline at end of file diff --git a/src/scraper/xhamster/xhamsterSearchController.ts b/src/scraper/xhamster/xhamsterSearchController.ts new file mode 100644 index 0000000..7bb7eeb --- /dev/null +++ b/src/scraper/xhamster/xhamsterSearchController.ts @@ -0,0 +1,56 @@ +import { load } from "cheerio"; +import LustPress from "../../LustPress"; +import { ISearchVideoData } from "../../interfaces"; + +const lust = new LustPress(); + +export async function scrapeContent(url: string) { + try { + const res = await lust.fetchBody(url); + const $ = load(res); + + class XhamsterSearch { + search: any; + constructor() { + const views = $("div.video-thumb-views") + .map((i, el) => { + const views = $(el).text(); + return views; + }).get(); + const duration = $("span[data-role='video-duration']") + .map((i, el) => { + const duration = $(el).text(); + return duration; + }).get(); + this.search = $("a.video-thumb__image-container") + .map((i, el) => { + const link = $(el).attr("href"); + + return { + link: `${link}`, + id: link?.split("/")[3] + "/" + link?.split("/")[4], + title: $(el).find("img").attr("alt"), + image: $(el).find("img").attr("src"), + duration: duration[i], + views: views[i], + video: $(el).attr("data-previewvideo"), + }; + }).get(); + } + } + + const xh = new XhamsterSearch(); + if (xh.search.length === 0) throw Error("No result found"); + const data = xh.search as unknown as string[]; + const result: ISearchVideoData = { + success: true, + data: data, + source: url, + }; + return result; + + } catch (err) { + const e = err as Error; + throw Error(e.message); + } +} \ No newline at end of file diff --git a/src/scraper/xnxx/xnxxGetController.ts b/src/scraper/xnxx/xnxxGetController.ts new file mode 100644 index 0000000..3683047 --- /dev/null +++ b/src/scraper/xnxx/xnxxGetController.ts @@ -0,0 +1,102 @@ +import { load } from "cheerio"; +import LustPress from "../../LustPress"; +import { IVideoData } from "../../interfaces"; + +const lust = new LustPress(); + +export async function scrapeContent(url: string) { + try { + console.log(url); + const resolve = await lust.fetchBody(url); + const $ = load(resolve); + + class Xnxx { + link: string; + id: string; + title: string; + image: string; + duration: string; + views: string; + uploaded: string; + action: string[]; + upVote: string; + downVote: string; + favVote: string; + tags: string[]; + models: string[]; + thumbnail: string; + bigimg: string; + video: string; + constructor() { + const thumb = $("script") + .map((i, el) => { + return $(el).text(); + }).get() + .filter((el) => el.includes("html5player.setThumbSlideBig"))[0] || "None"; + + this.thumbnail = thumb.match(/html5player.setThumbSlideBig\((.*?)\)/)?.[1] || "None"; + this.bigimg = thumb.match(/html5player.setThumbUrl169\((.*?)\)/)?.[1] || "None"; + this.video = thumb.match(/html5player.setVideoUrlHigh\((.*?)\)/)?.[1] || "None"; + this.link = $("meta[property='og:url']").attr("content") || "None"; + this.id = this.link.split(".com/")[1] || "None"; + this.title = $("meta[property='og:title']").attr("content") || "None"; + this.image = $("meta[property='og:image']").attr("content") || "None"; + this.duration = $("meta[property='og:duration']").attr("content") || "None"; + this.views = $("span.metadata").text() || "None"; + this.views = this.views.split("-")[2] || "None"; + this.uploaded = $("script[type='application/ld+json']").text() || "None"; + this.uploaded = this.uploaded + .split("uploadDate")[1] + .split("}")[0] + .split(":")[1] + .replace(/"/g, "") + .replace(/,/g, "") || "None"; + this.action = $("span.vote-actions") + .find("span.value") + .map((i, el) => { + return $(el).text(); + }).get(); + + this.upVote = this.action[0] || "None"; + this.downVote = this.action[1] || "None"; + this.favVote = $("span.rating-box.value").text() || "None"; + this.models = $("a.is-pornstar") + .map((i, el) => { + return $(el).text(); + }).get(); + this.tags = $("div.metadata-row.video-tags") + .find("a") + .map((i, el) => { + return $(el).text(); + }).get(); + + } + } + + const x = new Xnxx(); + + const data: IVideoData = { + success: true, + data: { + title: lust.removeHtmlTagWithoutSpace(x.title), + id: x.id, + image: x.image, + duration: lust.secondToMinute(Number(x.duration)), + views: lust.removeHtmlTag(x.views), + rating: x.favVote, + uploaded: x.uploaded.trim(), + upvoted: x.upVote, + downvoted: x.downVote, + models: x.models, + tags: x.tags.filter((el) => el !== "Edit tags and models") + }, + source: x.link, + assets: lust.removeAllSingleQuoteOnArray([x.thumbnail, x.bigimg, x.video]) + }; + return data; + + } catch (err) { + const e = err as Error; + throw Error(e.message); + } +} \ No newline at end of file diff --git a/src/scraper/xnxx/xnxxGetRelatedController.ts b/src/scraper/xnxx/xnxxGetRelatedController.ts new file mode 100644 index 0000000..8ffec25 --- /dev/null +++ b/src/scraper/xnxx/xnxxGetRelatedController.ts @@ -0,0 +1,55 @@ +import { load } from "cheerio"; +import LustPress from "../../LustPress"; +import c from "../../utils/options"; +import { ISearchVideoData } from "../../interfaces"; + +const lust = new LustPress(); + +export async function scrapeContent(url: string) { + try { + const res = await lust.fetchBody(url); + const $ = load(res); + + class PornhubSearch { + search: object[]; + data: object; + constructor() { + // in
get