Compare commits
2 Commits
003aff49f9
...
e2124acad2
| Author | SHA1 | Date |
|---|---|---|
|
|
e2124acad2 | |
|
|
37275f8930 |
|
|
@ -192,9 +192,6 @@ module.exports = {
|
|||
'traxxx',
|
||||
// porn doe
|
||||
'forbondage',
|
||||
'score',
|
||||
// porncz
|
||||
'porncz',
|
||||
],
|
||||
},
|
||||
profiles: [
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "traxxx",
|
||||
"version": "1.245.26",
|
||||
"version": "1.245.27",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "traxxx",
|
||||
"version": "1.245.26",
|
||||
"version": "1.245.27",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.458.0",
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
"connect-session-knex": "^4.0.0",
|
||||
"convert": "^4.14.0",
|
||||
"cookie": "^0.6.0",
|
||||
"css": "^3.0.0",
|
||||
"csv-parse": "^6.1.0",
|
||||
"csv-stringify": "^6.4.4",
|
||||
"date-fns": "^2.30.0",
|
||||
|
|
@ -93,7 +94,7 @@
|
|||
"tunnel": "0.0.6",
|
||||
"ua-parser-js": "^1.0.37",
|
||||
"undici": "^5.28.1",
|
||||
"unprint": "^0.18.7",
|
||||
"unprint": "^0.18.11",
|
||||
"url-pattern": "^1.0.3",
|
||||
"v-tooltip": "^2.1.3",
|
||||
"video.js": "^8.6.1",
|
||||
|
|
@ -6269,6 +6270,17 @@
|
|||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||
"bin": {
|
||||
"atob": "bin/atob.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.23",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.23.tgz",
|
||||
|
|
@ -7807,6 +7819,16 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/css": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
|
||||
"integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.4",
|
||||
"source-map": "^0.6.1",
|
||||
"source-map-resolve": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/css-loader": {
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz",
|
||||
|
|
@ -8055,6 +8077,14 @@
|
|||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
|
||||
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
|
||||
},
|
||||
"node_modules/decode-uri-component": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
|
||||
"integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/decompress-response": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
|
||||
|
|
@ -19072,6 +19102,16 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-resolve": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
|
||||
"integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
|
||||
"deprecated": "See https://github.com/lydell/source-map-resolve#deprecated",
|
||||
"dependencies": {
|
||||
"atob": "^2.1.2",
|
||||
"decode-uri-component": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
|
|
@ -20340,9 +20380,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/unprint": {
|
||||
"version": "0.18.7",
|
||||
"resolved": "https://registry.npmjs.org/unprint/-/unprint-0.18.7.tgz",
|
||||
"integrity": "sha512-Su7SQ7UxvM5SHuvkLmSGMiWi+nS6Qh3489qqbPYaqvH9DFBDc5C4544mGyysU/7ZKO+5RtAi59prVTNPo8rlSw==",
|
||||
"version": "0.18.11",
|
||||
"resolved": "https://registry.npmjs.org/unprint/-/unprint-0.18.11.tgz",
|
||||
"integrity": "sha512-mHOfweWWLqhEIRnjhdqCzEpHhIx+m/GwE2eDvJNNbnVEPbV8q8EaN6eGH3vkcAwDVgNIOakZaTZFK+VKy13Lsg==",
|
||||
"dependencies": {
|
||||
"bottleneck": "^2.19.5",
|
||||
"cookie": "^1.1.1",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "traxxx",
|
||||
"version": "1.245.26",
|
||||
"version": "1.245.27",
|
||||
"description": "All the latest porn releases in one place",
|
||||
"main": "src/app.js",
|
||||
"scripts": {
|
||||
|
|
@ -93,6 +93,7 @@
|
|||
"connect-session-knex": "^4.0.0",
|
||||
"convert": "^4.14.0",
|
||||
"cookie": "^0.6.0",
|
||||
"css": "^3.0.0",
|
||||
"csv-parse": "^6.1.0",
|
||||
"csv-stringify": "^6.4.4",
|
||||
"date-fns": "^2.30.0",
|
||||
|
|
@ -152,7 +153,7 @@
|
|||
"tunnel": "0.0.6",
|
||||
"ua-parser-js": "^1.0.37",
|
||||
"undici": "^5.28.1",
|
||||
"unprint": "^0.18.7",
|
||||
"unprint": "^0.18.11",
|
||||
"url-pattern": "^1.0.3",
|
||||
"v-tooltip": "^2.1.3",
|
||||
"video.js": "^8.6.1",
|
||||
|
|
|
|||
|
|
@ -2679,6 +2679,10 @@ const aliases = [
|
|||
name: 'threesome - fmm',
|
||||
for: 'mfm',
|
||||
},
|
||||
{
|
||||
name: 'threesome (fmm)', // doesn't usually mean bisexual
|
||||
for: 'mfm',
|
||||
},
|
||||
{
|
||||
name: '4k ultra hd',
|
||||
for: '4k',
|
||||
|
|
|
|||
|
|
@ -707,7 +707,6 @@ const networks = [
|
|||
slug: 'score',
|
||||
name: 'SCORE',
|
||||
url: 'https://www.scorepass.com',
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
slug: 'sexyhub',
|
||||
|
|
|
|||
|
|
@ -9384,6 +9384,7 @@ const sites = [
|
|||
{
|
||||
name: 'Czech Deviant',
|
||||
slug: 'czechdeviant',
|
||||
delete: true,
|
||||
url: 'https://www.czechdeviant.com',
|
||||
parent: 'porncz',
|
||||
parameters: {
|
||||
|
|
@ -9400,7 +9401,7 @@ const sites = [
|
|||
},
|
||||
},
|
||||
{
|
||||
name: 'Fuckingoffice',
|
||||
name: 'Fucking Office',
|
||||
slug: 'fuckingoffice',
|
||||
url: 'https://www.fuckingoffice.com',
|
||||
parent: 'porncz',
|
||||
|
|
@ -11339,6 +11340,951 @@ const sites = [
|
|||
},
|
||||
},
|
||||
// SCORE
|
||||
{
|
||||
name: '18 Eighteen',
|
||||
slug: '18eighteen',
|
||||
url: 'https://www.18eighteen.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/xxx-teen-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '40 Something Mag',
|
||||
slug: '40somethingmag',
|
||||
url: 'https://www.40somethingmag.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/xxx-mature-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '50 Plus MILFs',
|
||||
slug: '50plusmilfs',
|
||||
url: 'https://www.50plusmilfs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/xxx-milf-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '60 Plus MILFs',
|
||||
slug: '60plusmilfs',
|
||||
url: 'https://www.60plusmilfs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/xxx-granny-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Anal QTs',
|
||||
slug: 'analqts',
|
||||
url: 'https://www.analqts.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/anal-sex-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Ashley Sage Ellison',
|
||||
slug: 'ashleysageellison',
|
||||
url: 'https://www.ashleysageellison.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Asian Coochies',
|
||||
slug: 'asiancoochies',
|
||||
url: 'https://www.asiancoochies.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/asian-porn-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Autumn Jade',
|
||||
slug: 'autumnjade',
|
||||
url: 'https://www.autumn-jade.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Boob Alexya',
|
||||
slug: 'bigboobalexya',
|
||||
url: 'https://www.bigboobalexya.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Boob Bundle',
|
||||
slug: 'bigboobbundle',
|
||||
url: 'https://www.bigboobbundle.com',
|
||||
delete: true,
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Boob Daria',
|
||||
slug: 'bigboobdaria',
|
||||
url: 'https://www.bigboobdaria.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Boobs POV',
|
||||
slug: 'bigboobspov',
|
||||
url: 'https://www.bigboobspov.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/big-boob-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Boob Vanessa Y',
|
||||
slug: 'bigboobvanessay',
|
||||
url: 'https://www.bigboobvanessay.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Tit Angela White',
|
||||
slug: 'bigtitangelawhite',
|
||||
url: 'https://www.bigtitangelawhite.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Tit Hitomi',
|
||||
slug: 'bigtithitomi',
|
||||
url: 'https://www.bigtithitomi.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Tit Hooker',
|
||||
slug: 'bigtithooker',
|
||||
url: 'https://www.bigtithooker.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/big-boob-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Tit Katie Thornton',
|
||||
slug: 'bigtitkatiethornton',
|
||||
url: 'https://www.bigtitkatiethornton.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Tit Terry Nova',
|
||||
slug: 'bigtitterrynova',
|
||||
url: 'https://www.bigtitterrynova.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Big Tit Venera',
|
||||
slug: 'bigtitvenera',
|
||||
url: 'https://www.bigtitvenera.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Black And Stacked',
|
||||
slug: 'blackandstacked',
|
||||
url: 'https://www.blackandstacked.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Boned At Home',
|
||||
slug: 'bonedathome',
|
||||
url: 'https://www.bonedathome.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/amateur-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Bootylicious',
|
||||
slug: 'bootyliciousmag',
|
||||
url: 'https://www.bootyliciousmag.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/big-booty-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Angelique',
|
||||
slug: 'bustyangelique',
|
||||
url: 'https://www.bustyangelique.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Arianna',
|
||||
slug: 'bustyarianna',
|
||||
url: 'https://www.bustyarianna.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Danni Ashe',
|
||||
slug: 'bustydanniashe',
|
||||
url: 'https://www.bustydanniashe.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Dusty Stash',
|
||||
slug: 'bustydustystash',
|
||||
url: 'https://www.bustydustystash.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Ines Cudna',
|
||||
slug: 'bustyinescudna',
|
||||
url: 'https://www.bustyinescudna.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Kelly Kay',
|
||||
slug: 'bustykellykay',
|
||||
url: 'https://www.bustykellykay.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Kerry Marie',
|
||||
slug: 'bustykerrymarie',
|
||||
url: 'https://www.bustykerrymarie.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Lezzies',
|
||||
slug: 'bustylezzies',
|
||||
url: 'https://www.bustylezzies.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/lesbian-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Lorna Morgan',
|
||||
slug: 'bustylornamorgan',
|
||||
url: 'https://www.bustylornamorgan.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Merilyn',
|
||||
slug: 'bustymerilyn',
|
||||
url: 'https://www.bustymerilyn.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Old Sluts',
|
||||
slug: 'bustyoldsluts',
|
||||
url: 'https://www.bustyoldsluts.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/big-tit-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Busty Sammie Black',
|
||||
slug: 'bustysammieblack',
|
||||
url: 'https://www.bustysammieblack.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Cherry Brady',
|
||||
slug: 'cherrybrady',
|
||||
url: 'https://www.cherrybrady.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Chicks on Black Dicks',
|
||||
slug: 'chicksonblackdicks',
|
||||
url: 'https://www.chicksonblackdicks.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/interracial-porn-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Chloes World',
|
||||
slug: 'chloesworld',
|
||||
url: 'https://www.chloesworld.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Christy Marks',
|
||||
slug: 'christymarks',
|
||||
url: 'https://www.christymarks.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Cock 4 Stepmom',
|
||||
slug: 'cock4stepmom',
|
||||
url: 'https://www.cock4stepmom.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/stepmom-xxx-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Codi Vore XXX',
|
||||
slug: 'codivorexxx',
|
||||
url: 'https://www.codivorexxx.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Creampie for Granny',
|
||||
slug: 'creampieforgranny',
|
||||
url: 'https://www.creampieforgranny.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/milf-creampie-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Crystal Gunns World',
|
||||
slug: 'crystalgunnsworld',
|
||||
url: 'https://www.crystalgunnsworld.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Daylene Rio',
|
||||
slug: 'daylenerio',
|
||||
url: 'https://www.daylenerio.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Desiraes World',
|
||||
slug: 'desiraesworld',
|
||||
url: 'https://www.desiraesworld.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Diane Poppos',
|
||||
slug: 'dianepoppos',
|
||||
url: 'https://www.dianepoppos.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Ebony Thots',
|
||||
slug: 'ebonythots',
|
||||
url: 'https://www.ebonythots.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/black-girl-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Eva Notty Videos',
|
||||
slug: 'evanottyvideos',
|
||||
url: 'https://www.evanottyvideos.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Feed Her Fuck Her',
|
||||
slug: 'feedherfuckher',
|
||||
url: 'https://www.feedherfuckher.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/bbw-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Flat And Fucked MILFs',
|
||||
slug: 'flatandfuckedmilfs',
|
||||
url: 'https://www.flatandfuckedmilfs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/xxx-milf-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Granny Gets A Facial',
|
||||
slug: 'grannygetsafacial',
|
||||
url: 'https://www.grannygetsafacial.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/granny-facial-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Granny Loves BBC',
|
||||
slug: 'grannylovesbbc',
|
||||
url: 'https://www.grannylovesbbc.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/bbc-granny-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Granny Loves Young Cock',
|
||||
slug: 'grannylovesyoungcock',
|
||||
url: 'https://www.grannylovesyoungcock.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/xxx-granny-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Hairy Coochies',
|
||||
slug: 'hairycoochies',
|
||||
url: 'https://www.hairycoochies.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/hairy-pussy-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Home Alone MILFs',
|
||||
slug: 'homealonemilfs',
|
||||
url: 'https://www.homealonemilfs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/milf-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Horny Asian MILFs',
|
||||
slug: 'hornyasianmilfs',
|
||||
url: 'https://www.hornyasianmilfs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/asian-milf-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'I Boned Your Mom',
|
||||
slug: 'ibonedyourmom',
|
||||
url: 'https://www.ibonedyourmom.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/mom-fucking-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'I Fucked the Boss',
|
||||
slug: 'ifuckedtheboss',
|
||||
url: 'https://www.ifuckedtheboss.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/working-girl-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Jessica Turner',
|
||||
slug: 'jessicaturner',
|
||||
url: 'https://www.jessicaturner.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Joana Bliss',
|
||||
slug: 'joanabliss',
|
||||
url: 'https://www.joanabliss.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Julia Miles',
|
||||
slug: 'juliamiles',
|
||||
url: 'https://www.juliamiles.co.uk',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Karina Hart',
|
||||
slug: 'karinahart',
|
||||
url: 'https://www.karinahart.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Karla James',
|
||||
slug: 'karlajames',
|
||||
url: 'https://www.karlajames.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Latina Coochies',
|
||||
slug: 'latinacoochies',
|
||||
url: 'https://www.latinacoochies.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/latina-porn-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Latin Mommas',
|
||||
slug: 'latinmommas',
|
||||
url: 'https://www.latinmommas.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/latina-milf-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Leanne Crow Videos',
|
||||
slug: 'leannecrowvideos',
|
||||
url: 'https://www.leannecrowvideos.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Leg Sex',
|
||||
slug: 'legsex',
|
||||
url: 'https://www.legsex.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/foot-fetish-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Linseys World',
|
||||
slug: 'linseysworld',
|
||||
url: 'https://www.linseysworld.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Mega Tits Minka',
|
||||
slug: 'megatitsminka',
|
||||
url: 'https://www.megatitsminka.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Micky Bells',
|
||||
slug: 'mickybells',
|
||||
url: 'https://www.mickybells.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'MILF Bundle',
|
||||
slug: 'milfbundle',
|
||||
delete: true,
|
||||
url: 'https://www.milfbundle.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/milf-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'MILF Threesomes',
|
||||
slug: 'milfthreesomes',
|
||||
url: 'https://www.milfthreesomes.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/milf-group-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'MILF Tugs',
|
||||
slug: 'milftugs',
|
||||
url: 'https://www.milftugs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/milf-handjob-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Milly Marks',
|
||||
slug: 'millymarks',
|
||||
url: 'https://www.millymarks.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Mommys Toy Time',
|
||||
slug: 'mommystoytime',
|
||||
url: 'https://www.mommystoytime.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/milf-sex-toy-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Natalie Fiore',
|
||||
slug: 'nataliefiore',
|
||||
url: 'https://www.nataliefiore.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Naughty Footjobs',
|
||||
slug: 'naughtyfootjobs',
|
||||
url: 'https://www.naughtyfootjobs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/foot-job-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Naughty Mag',
|
||||
slug: 'naughtymag',
|
||||
url: 'https://www.naughtymag.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/amateur-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Naughty Tugs',
|
||||
slug: 'naughtytugs',
|
||||
url: 'https://www.naughtytugs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/hand-job-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Nicole Peters',
|
||||
slug: 'nicolepeters',
|
||||
url: 'https://www.nicolepeters.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Old Horny MILFs',
|
||||
slug: 'oldhornymilfs',
|
||||
url: 'https://www.oldhornymilfs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/milf-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Picking Up Pussy',
|
||||
slug: 'pickinguppussy',
|
||||
url: 'https://www.pickinguppussy.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/xxx-teen-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Porn Loser',
|
||||
slug: 'pornloser',
|
||||
url: 'https://www.pornloser.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/amateur-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Porn Mega Load',
|
||||
slug: 'pornmegaload',
|
||||
delete: true,
|
||||
url: 'https://www.pornmegaload.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/hd-porn-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Renee Ross Videos',
|
||||
slug: 'reneerossvideos',
|
||||
url: 'https://www.reneerossvideos.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Roxi Red',
|
||||
slug: 'roxired',
|
||||
url: 'https://www.roxired.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'SaRennas World',
|
||||
slug: 'sarennasworld',
|
||||
url: 'https://www.sarennasworld.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Score Classics',
|
||||
slug: 'scoreclassics',
|
||||
url: 'https://www.scoreclassics.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/classic-boob-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Scoreland',
|
||||
slug: 'scoreland',
|
||||
url: 'https://www.scoreland.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/big-boob-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Scoreland2',
|
||||
slug: 'scoreland2',
|
||||
url: 'https://www.scoreland2.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/big-boob-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'SCOREtv',
|
||||
slug: 'scoretv',
|
||||
delete: true,
|
||||
parent: 'score',
|
||||
},
|
||||
{
|
||||
name: 'Scoreland TV',
|
||||
slug: 'scorelandtv',
|
||||
delete: true,
|
||||
url: 'https://www.scorepass.com/scorelandtv',
|
||||
parent: 'score',
|
||||
priority: 1,
|
||||
},
|
||||
{
|
||||
name: 'Score Videos',
|
||||
slug: 'scorevideos',
|
||||
url: 'https://www.scorevideos.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/porn-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Sha Rizel Videos',
|
||||
slug: 'sharizelvideos',
|
||||
url: 'https://www.sharizelvideos.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Silver Sluts',
|
||||
slug: 'silversluts',
|
||||
url: 'https://www.silversluts.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/granny-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Stacy Vandenberg Boobs',
|
||||
slug: 'stacyvandenbergboobs',
|
||||
url: 'https://www.stacyvandenbergboobs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Susie Wildin',
|
||||
slug: 'susiewildin',
|
||||
url: 'https://www.susiewildin.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Tawny Peaks',
|
||||
slug: 'tawnypeaks',
|
||||
url: 'https://www.tawny-peaks.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Tiffany Towers',
|
||||
slug: 'tiffanytowers',
|
||||
url: 'https://www.tiffany-towers.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Tits And Tugs',
|
||||
slug: 'titsandtugs',
|
||||
url: 'https://www.titsandtugs.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/big-boob-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'TNA Tryouts',
|
||||
slug: 'tnatryouts',
|
||||
url: 'https://www.tnatryouts.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/xxx-teen-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Valory Irene',
|
||||
slug: 'valoryirene',
|
||||
url: 'https://www.valoryirene.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'XL Girls',
|
||||
slug: 'xlgirls',
|
||||
url: 'https://www.xlgirls.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/bbw-videos',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Your Mom Loves Anal',
|
||||
slug: 'yourmomlovesanal',
|
||||
url: 'https://www.yourmomlovesanal.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/anal-milf-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Your Mom's Got Big Tits",
|
||||
slug: 'yourmomsgotbigtits',
|
||||
url: 'https://www.yourmomsgotbigtits.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/big-tit-mom-scenes',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Your Wife My Meat',
|
||||
slug: 'yourwifemymeat',
|
||||
url: 'https://www.yourwifemymeat.com',
|
||||
parent: 'score',
|
||||
parameters: {
|
||||
path: '/wife-fucking-scenes',
|
||||
},
|
||||
},
|
||||
/* legacy
|
||||
{
|
||||
name: '18 Eighteen',
|
||||
slug: '18eighteen',
|
||||
|
|
@ -11874,6 +12820,7 @@ const sites = [
|
|||
url: 'https://www.milfbundle.com/yourwifemymeat',
|
||||
parent: 'score',
|
||||
},
|
||||
*/
|
||||
// SEX LIKE REAL
|
||||
{
|
||||
name: 'Sex Like Real',
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ function curateEntity(entity, includeParameters = false) {
|
|||
id: entity.id,
|
||||
name: entity.name,
|
||||
url: entity.url,
|
||||
origin: new URL(entity.url).origin,
|
||||
origin: entity.url && new URL(entity.url).origin,
|
||||
description: entity.description,
|
||||
slug: entity.slug,
|
||||
type: entity.type,
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ function scrapeProfile({ query }) {
|
|||
const birthday = new Date(Date.UTC(0, Number(month) - 1, Number(day)));
|
||||
|
||||
if (profile.age) {
|
||||
birthday.setUTCFullYear(new Date().getFullYear() - profile.age); // indicate birth year is unknown
|
||||
birthday.setUTCFullYear(new Date().getFullYear() - profile.age);
|
||||
} else {
|
||||
birthday.setUTCFullYear(0); // indicate birth year is unknown
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,253 +1,276 @@
|
|||
'use strict';
|
||||
|
||||
const { ex, exa, get } = require('../utils/q');
|
||||
const unprint = require('unprint');
|
||||
|
||||
const slugify = require('../utils/slugify');
|
||||
const http = require('../utils/http');
|
||||
const { heightToCm, lbsToKg } = require('../utils/convert');
|
||||
const { stripQuery } = require('../utils/url');
|
||||
const { convert } = require('../utils/convert');
|
||||
|
||||
function scrapePhotos(html) {
|
||||
const { qis } = ex(html, '#photos-page');
|
||||
const photos = qis('img');
|
||||
const sizeRegex = /_lg|_xl|_tn/;
|
||||
|
||||
return photos.map((photo) => [
|
||||
photo
|
||||
.replace('x_800', 'x_xl')
|
||||
.replace('_tn', ''),
|
||||
photo,
|
||||
]);
|
||||
}
|
||||
|
||||
async function fetchPhotos(url) {
|
||||
const res = await http.get(url);
|
||||
|
||||
if (res.statusCode === 200) {
|
||||
return scrapePhotos(res.body.toString(), url);
|
||||
function resizeSrc(src) {
|
||||
if (!src) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [];
|
||||
return Array.from(new Set([
|
||||
src.replace(sizeRegex, '_1280'),
|
||||
src.replace(sizeRegex, '_800'),
|
||||
src.replace(sizeRegex, '_xl'),
|
||||
src,
|
||||
]));
|
||||
}
|
||||
|
||||
function scrapeAll(html, site) {
|
||||
return exa(html, '.container .video, .container-fluid .video').map(({ q, qa, qd, ql }) => {
|
||||
function scrapeAll(scenes, channel, parameters) {
|
||||
return scenes.map(({ query }) => {
|
||||
const release = {};
|
||||
const poster = query.img('.item-img img');
|
||||
|
||||
release.title = q('.title, .i-title', true);
|
||||
const url = stripQuery(query.url('a.i-title, .item-img a'));
|
||||
|
||||
const linkEl = q('a');
|
||||
const url = new URL(linkEl.href);
|
||||
release.url = `${url.origin}${url.pathname}`;
|
||||
release.title = query.content('a.i-title, h2.i-title');
|
||||
release.duration = query.duration('.time-ol');
|
||||
|
||||
// this is a photo album, not a scene (used for profiles)
|
||||
if (/photos\//.test(url)) return null;
|
||||
release.date = query.date('.i-date', ['MMM. Do', 'MMM. YYYY'], { match: /(\w+\.? \d{1,2}\w+)|(\w+\.? \d{4})/ });
|
||||
|
||||
[release.entryId] = url.pathname.split('/').slice(-2);
|
||||
if (!release.date) {
|
||||
const date = query.dateAgo('.i-date');
|
||||
|
||||
release.date = qd('.i-date', 'MMM DD', /\w+ \d{1,2}$/)
|
||||
|| qd('.dt-box', 'MMM.DD YYYY');
|
||||
release.actors = site?.parameters?.actors || qa('.model, .i-model', true);
|
||||
release.duration = ql('.i-amount, .amount');
|
||||
|
||||
const posterEl = q('.item-img img');
|
||||
|
||||
if (posterEl) {
|
||||
release.poster = `https:${posterEl.src}`;
|
||||
if (date) {
|
||||
release.date = date.date;
|
||||
release.datePrecision = date.precision === 'week' ? 'month' : date.precision;
|
||||
}
|
||||
}
|
||||
|
||||
if (posterEl?.dataset.gifPreview) {
|
||||
release.teaser = {
|
||||
src: `https:${posterEl.dataset.gifPreview}`,
|
||||
};
|
||||
release.actors = query.content('.i-model').split(',').map((actor) => actor.trim());
|
||||
|
||||
if (url.includes('join.') || url.includes('/join')) {
|
||||
// no link available, attempt to reconstruct from poster URL
|
||||
const entryId = poster?.match(/posting_(\d+)/)?.[1];
|
||||
|
||||
if (entryId) {
|
||||
// we can get deep data from this
|
||||
release.entryId = entryId;
|
||||
release.url = `${channel.origin}${parameters.path}/${slugify(release.actors[0], '-', { lower: false })}/${entryId}/`;
|
||||
} else {
|
||||
// lost cause, make up entryId to register shallow data
|
||||
release.entryId = slugify(release.title);
|
||||
}
|
||||
} else {
|
||||
release.url = url;
|
||||
release.entryId = new URL(release.url).pathname.match(/\/(\d+)\/?$/)[1];
|
||||
}
|
||||
|
||||
if (poster) {
|
||||
const caps = Array.from(new Set(Array.from({ length: 6 }, (_src, index) => {
|
||||
const file = `${String(index + 1).padStart(2, '0')}_lg`;
|
||||
|
||||
return poster.replace(/0\d_lg/, file);
|
||||
}))).map((src) => resizeSrc(src));
|
||||
|
||||
release.poster = Array.from({ length: caps[0].length }).flatMap((_value, index) => caps.map((src) => src[index])); // try all the best sources first
|
||||
|
||||
if (caps.length > 1) {
|
||||
release.caps = caps;
|
||||
}
|
||||
}
|
||||
|
||||
release.photos = query.imgs('.thumbs img'); // cards layout
|
||||
|
||||
release.teaser = [
|
||||
query.video('.preview-clip source[type="video/mp4"]'),
|
||||
query.video('.preview-clip source[type="video/webm"]'),
|
||||
].filter(Boolean);
|
||||
|
||||
return release;
|
||||
}).filter(Boolean);
|
||||
});
|
||||
}
|
||||
|
||||
async function scrapeScene(html, url, site) {
|
||||
const { qu } = ex(html, '#videos-page, #content section');
|
||||
async function fetchLatest(channel, page = 1, { parameters }) {
|
||||
const res = await unprint.get(`${channel.origin}${parameters.path}/?page=${page}`, {
|
||||
interface: 'request', // seemingly less prone to HTTPParserError: Response does not match the HTTP/1.1 protocol (Invalid character in chunk size)
|
||||
selectAll: '.videos .video, .video-wide', // video-wide for cards layout e.g. Big Boobs POV
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
return scrapeAll(res.context, channel, parameters);
|
||||
}
|
||||
|
||||
return res.status;
|
||||
}
|
||||
|
||||
function scrapeScene({ query }, url) {
|
||||
const release = {};
|
||||
|
||||
[release.entryId] = new URL(url).pathname.split('/').slice(-2);
|
||||
const info = Object.fromEntries(query.all('.stat').map((infoEl) => [
|
||||
slugify(unprint.query.content(infoEl, '.label')),
|
||||
unprint.query.content(infoEl, '.value'),
|
||||
]));
|
||||
|
||||
release.title = qu.q('h2.text-uppercase, h2.title, #breadcrumb-top + h1', true)
|
||||
|| qu.q('h1.m-title', true)?.split(/»|\//).slice(-1)[0].trim();
|
||||
release.description = qu.text('.p-desc, .desc');
|
||||
release.url = stripQuery(url);
|
||||
release.entryId = new URL(url).pathname.match(/\/(\d+)\/?$/)[1];
|
||||
|
||||
release.actors = qu.all('.value a[href*=models], .value a[href*=performer], .value a[href*=teen-babes]', true);
|
||||
release.title = query.content('.p-desc h2, #videos_page-page h1');
|
||||
release.description = query.text('.p-desc, .desc');
|
||||
|
||||
if (release.actors.length === 0) {
|
||||
const actorEl = qu.all('.stat').find((stat) => /Featuring/.test(stat.textContent));
|
||||
const actorString = qu.text(actorEl);
|
||||
release.date = unprint.extractDate(info.date, 'MMMM Do, YYYY', { match: /\w+ \d{1,2}\w+, \d{4}/ });
|
||||
release.duration = unprint.extractDuration(info.duration) || Number(info.duration) * 60 || null;
|
||||
|
||||
release.actors = actorString?.split(/,\band\b|,/g).map((actor) => actor.trim()) || [];
|
||||
}
|
||||
release.actors = query.all('//span[contains(text(), "Featuring")]/following-sibling::span/a').map((actorEl) => ({
|
||||
name: unprint.query.content(actorEl),
|
||||
url: stripQuery(unprint.query.url(actorEl, null)),
|
||||
}));
|
||||
|
||||
if (release.actors.length === 0 && site.parameters?.actors) release.actors = site.parameters.actors;
|
||||
release.tags = query.contents('.p-desc a[href*="tag/"], .desc a[href*="tag/"]');
|
||||
|
||||
release.tags = qu.all('a[href*=tag]', true);
|
||||
const style = query.content('.vp style');
|
||||
const poster = query.img('#videos_page-page .item-img img') || style?.match(/background-image: url\('(http[\w.:/_-]+)'\);/)?.[1];
|
||||
const fallbackPoster = resizeSrc(query.img('meta[itemprop="image"]', { attribute: 'content' })); // usually a different image
|
||||
|
||||
const dateEl = qu.all('.value').find((el) => /\w+ \d+\w+, \d{4}/.test(el.textContent));
|
||||
release.date = qu.date(dateEl, null, 'MMMM Do, YYYY')
|
||||
|| qu.date('.date', 'MMMM Do, YYYY', /\w+ \d{1,2}\w+, \d{4}/)
|
||||
|| qu.date('.info .holder', 'MM/DD/YYYY', /\d{2}\/\d{2}\/\d{4}/);
|
||||
const photos = query.all('.gallery .thumb').map((imgEl) => {
|
||||
const link = unprint.query.url(imgEl, 'a');
|
||||
const img = unprint.query.img(imgEl, 'img');
|
||||
const isJoin = !link || link.includes('join.') || link.includes('/join');
|
||||
|
||||
const durationEl = qu.all('value').find((el) => /\d{1,3}:\d{2}/.test(el.textContent));
|
||||
release.duration = qu.dur(durationEl);
|
||||
return Array.from(new Set([
|
||||
...isJoin ? [] : [link],
|
||||
img.replace('_tn', ''),
|
||||
img,
|
||||
]));
|
||||
});
|
||||
|
||||
release.poster = qu.poster('video') || qu.img('.flowplayer img') || html.match(/posterImage: '(.*\.jpg)'/)?.[1] || null; // _800.jpg is larger than _xl.jpg in landscape
|
||||
const photosUrl = qu.url('.stat a[href*=photos]');
|
||||
if (poster) {
|
||||
release.poster = resizeSrc(poster);
|
||||
|
||||
if (photosUrl) {
|
||||
release.photos = await fetchPhotos(photosUrl);
|
||||
if (fallbackPoster?.includes(poster)) {
|
||||
release.photos = [fallbackPoster, ...photos]; // fallback poster isn't usually in photoset, append
|
||||
} else {
|
||||
release.photos = photos;
|
||||
}
|
||||
} else {
|
||||
release.photos = qu.imgs('img[src*=ThumbNails], .p-photos .tn img').map((photo) => [
|
||||
photo.replace('_tn', ''),
|
||||
photo,
|
||||
]);
|
||||
release.poster = fallbackPoster;
|
||||
release.photos = photos;
|
||||
}
|
||||
|
||||
const trailers = qu.all('a[href*=Trailers]');
|
||||
|
||||
if (trailers) {
|
||||
release.trailer = trailers.map((trailer) => {
|
||||
const src = `https:${trailer.href}`;
|
||||
const format = trailer.textContent.trim().match(/^\w+/)[0].toLowerCase();
|
||||
const quality = parseInt(trailer.textContent.trim().match(/\d+([a-zA-Z]+)?$/)[0], 10);
|
||||
|
||||
return format === 'mp4' ? { src, quality } : null;
|
||||
}).filter(Boolean);
|
||||
}
|
||||
|
||||
const stars = qu.q('.rate-box').dataset.score;
|
||||
if (stars) release.rating = { stars };
|
||||
release.trailer = query.all('.vp video source').map((videoEl) => ({
|
||||
src: unprint.query.video(videoEl, null),
|
||||
quality: parseInt(unprint.query.attribute(videoEl, null, 'res'), 10) || null,
|
||||
}));
|
||||
|
||||
return release;
|
||||
}
|
||||
|
||||
function scrapeModels(html, actorName) {
|
||||
const { qa } = ex(html);
|
||||
const model = qa('.model a').find((link) => link.title === actorName);
|
||||
|
||||
return model?.href || null;
|
||||
}
|
||||
|
||||
async function fetchActorReleases(url, accReleases = []) {
|
||||
const res = await get(url);
|
||||
async function fetchScene(url, channel, baseRelease) {
|
||||
const res = await unprint.get(url, {
|
||||
interface: 'request',
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
const releases = accReleases.concat(scrapeAll(res.item.document.body.outerHTML));
|
||||
const nextPage = res.item.qu.url('.next-pg');
|
||||
|
||||
if (nextPage && new URL(nextPage).searchParams.has('page')) { // last page has 'next' button linking to join page
|
||||
return fetchActorReleases(nextPage, releases);
|
||||
}
|
||||
|
||||
return releases;
|
||||
return scrapeScene(res.context, url, channel, baseRelease);
|
||||
}
|
||||
|
||||
return null;
|
||||
return res.status;
|
||||
}
|
||||
|
||||
async function scrapeProfile(html, actorUrl, withReleases) {
|
||||
const { q, qa, qi } = ex(html, '#model-page');
|
||||
const profile = { gender: 'female' };
|
||||
function scrapeProfile({ query }, url) {
|
||||
const profile = { url };
|
||||
const { pathname } = new URL(url);
|
||||
|
||||
const bio = qa('.stat').reduce((acc, el) => {
|
||||
const prop = q(el, '.label', true).slice(0, -1);
|
||||
const key = slugify(prop, '_');
|
||||
const value = q(el, '.value', true);
|
||||
const bio = Object.fromEntries(query.all('.m-info .stat').map((bioEl) => [
|
||||
slugify(unprint.query.content(bioEl, '.label'), '_'),
|
||||
unprint.query.content(bioEl, '.value'),
|
||||
]));
|
||||
|
||||
return {
|
||||
...acc,
|
||||
[key]: value,
|
||||
};
|
||||
}, {});
|
||||
|
||||
if (bio.location) profile.residencePlace = bio.location.replace('Czech Repulic', 'Czech Republic'); // see Laura Lion
|
||||
|
||||
if (bio.birthday) {
|
||||
const birthMonth = bio.birthday.match(/^\w+/)[0].toLowerCase();
|
||||
const [birthDay] = bio.birthday.match(/\d+/);
|
||||
|
||||
profile.birthday = [birthMonth, birthDay]; // currently unused, not to be confused with birthdate
|
||||
if (pathname.includes('big-boob-models')) {
|
||||
profile.gender = 'female';
|
||||
}
|
||||
|
||||
if (bio.ethnicity) profile.ethnicity = bio.ethnicity;
|
||||
if (bio.hair_color) profile.hair = bio.hair_color;
|
||||
if (pathname.includes('male-performer')) {
|
||||
profile.gender = 'male';
|
||||
}
|
||||
|
||||
if (bio.height) profile.height = heightToCm(bio.height);
|
||||
if (bio.weight) profile.weight = lbsToKg(bio.weight);
|
||||
profile.avatar = query.img('.item-img a img:not([src*="posting"])');
|
||||
|
||||
if (bio.bra_size) profile.bust = bio.bra_size;
|
||||
if (bio.measurements) [, profile.waist, profile.hip] = bio.measurements.split('-');
|
||||
profile.placeOfResidence = bio.location;
|
||||
profile.ethnicity = bio.ethnicity;
|
||||
|
||||
if (bio.occupation) profile.occupation = bio.occupation;
|
||||
profile.height = convert(bio.height, 'cm');
|
||||
profile.weight = convert(bio.weight, 'lb', 'kg');
|
||||
|
||||
const avatar = qi('img');
|
||||
if (avatar) profile.avatar = avatar;
|
||||
if (bio.bra_size && bio.measurements) {
|
||||
profile.measurements = bio.measurements.replace(/^\d+-/, `${bio.bra_size}-`);
|
||||
} else {
|
||||
profile.measurements = bio.measurements || bio.bra_size;
|
||||
}
|
||||
|
||||
if (withReleases) {
|
||||
const { origin, pathname } = new URL(actorUrl);
|
||||
profile.releases = await fetchActorReleases(`${origin}${pathname}/scenes?page=1`);
|
||||
profile.hairColor = bio.hair_color;
|
||||
|
||||
const birthday = unprint.extractDate(bio.birthday, 'MMMM D', { match: /\w+.?\s+\d{1,2}/ });
|
||||
|
||||
if (birthday) {
|
||||
birthday.setFullYear(0); // indicate birth year is unknown
|
||||
profile.dateOfBirth = birthday;
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
async function fetchLatest(site, page = 1) {
|
||||
const latestPath = site.parameters?.path || '/big-boob-videos';
|
||||
const url = `${site.url}${latestPath}?page=${page}`;
|
||||
const res = await http.get(url);
|
||||
|
||||
if (res.statusCode === 200) {
|
||||
return scrapeAll(res.body.toString(), site);
|
||||
async function getActorUrl(actor) {
|
||||
if (actor.url) {
|
||||
return actor.url;
|
||||
}
|
||||
|
||||
return res.statusCode;
|
||||
}
|
||||
const searchRes = await unprint.post('https://www.scoreland.com/search-es/', {
|
||||
keywords: actor.name,
|
||||
's_filters[site]': 'all',
|
||||
's_filters[type]': 'models',
|
||||
}, {
|
||||
interface: 'request',
|
||||
form: true,
|
||||
followRedirects: false,
|
||||
});
|
||||
|
||||
async function fetchScene(url, site) {
|
||||
const res = await http.get(url);
|
||||
const res = await unprint.get(searchRes.headers.location, {
|
||||
interface: 'request',
|
||||
cookies: {
|
||||
cisession: searchRes.cookies.cisession,
|
||||
},
|
||||
// followRedirects: false,
|
||||
selectAll: '.li-item.model',
|
||||
});
|
||||
|
||||
if (res.statusCode === 200) {
|
||||
return scrapeScene(res.body.toString(), url, site);
|
||||
if (res.ok) {
|
||||
const actorEl = res.context.find(({ query }) => slugify(query.content('.i-model')) === actor.slug);
|
||||
const url = actorEl?.query.url('.i-model');
|
||||
|
||||
if (url) {
|
||||
// messy nats link pointing to unpredictable sites, all data seems to be available on scoreland
|
||||
const { pathname } = new URL(url);
|
||||
const actorPath = pathname.match(/\/[\w-]+\/\d+\/?$/);
|
||||
|
||||
if (actorPath) {
|
||||
return `https://www.scoreland.com/big-boob-models${actorPath[0]}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function fetchProfile({ name: actorName }, context, include, page = 1, source = 0) {
|
||||
const letter = actorName.charAt(0).toUpperCase();
|
||||
async function fetchProfile(actor) {
|
||||
const url = await getActorUrl(actor);
|
||||
|
||||
const sources = [
|
||||
`https://www.scoreland.com/big-boob-models/browse/${letter}/?page=${page}`,
|
||||
`https://www.50plusmilfs.com/xxx-milf-models/browse/${letter}/?page=${page}`,
|
||||
];
|
||||
if (url) {
|
||||
const res = await unprint.get(url, {
|
||||
interface: 'request',
|
||||
select: '#model-page',
|
||||
});
|
||||
|
||||
const url = sources[source];
|
||||
|
||||
const res = await http.get(url, {
|
||||
followRedirects: false,
|
||||
});
|
||||
|
||||
if (res.statusCode === 200) {
|
||||
const actorUrl = scrapeModels(res.body.toString(), actorName);
|
||||
|
||||
if (actorUrl) {
|
||||
const actorRes = await http.get(actorUrl);
|
||||
|
||||
if (actorRes.statusCode === 200) {
|
||||
return scrapeProfile(actorRes.body.toString(), actorUrl, include.scenes);
|
||||
}
|
||||
|
||||
return null;
|
||||
if (res.ok) {
|
||||
return scrapeProfile(res.context, url);
|
||||
}
|
||||
|
||||
return fetchProfile({ name: actorName }, context, include, page + 1, source);
|
||||
}
|
||||
|
||||
if (sources[source + 1]) {
|
||||
return fetchProfile({ name: actorName }, context, include, 1, source + 1);
|
||||
return res.status;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ const actors = [
|
|||
{ entity: 'testedefudelidade', name: 'May Akemi', fields: ['avatar'] },
|
||||
{ entity: 'sexlikereal', name: 'Agatha Vega', fields: ['avatar', 'birthPlace', 'height', 'weight', 'description'] },
|
||||
{ entity: 'porncz', name: 'Kama Oxi', fields: ['avatar', 'gender', 'birthCountry', 'ethnicity', 'age', 'hairColor', 'cup', 'naturalBoobs', 'hasTattoos'] },
|
||||
{ entity: 'score', name: 'Vanessa Blue', fields: ['avatar', 'gender', 'placeOfResidence', 'ethnicity', 'height', 'weight', 'measurements', 'hairColor', 'dateOfBirth'] },
|
||||
];
|
||||
|
||||
const actorScrapers = scrapers.actors;
|
||||
|
|
|
|||
Loading…
Reference in New Issue