Updated Hussie Pass scraper for new site design. Added cock size to profiles.

This commit is contained in:
DebaucheryLibrarian 2020-11-15 04:33:24 +01:00
parent b3a5d7f379
commit df9a6eac05
69 changed files with 267 additions and 145 deletions

View File

@ -166,6 +166,32 @@
</span>
</li>
<li
v-if="actor.penisLength || actor.penisGirth || actor.circumcised"
class="bio-item penis"
>
<dfn class="bio-label"><Icon icon="pencil-ruler" />Dick</dfn>
<span>
<Icon
v-if="actor.circumcised"
v-tooltip="'Circumcised'"
icon="page-break"
class="circumcised"
/>
<template v-if="actor.penisLengthMetric && actor.penisGirthMetric">
<span>{{ actor.penisLengthMetric }} * {{ actor.penisGirthMetric }} cm</span>
<span class="bio-segment">{{ actor.penisLengthImperial }}" * {{ actor.penisGirthImperial }}"</span>
</template>
<template v-else-if="actor.penisLengthMetric">
<span>{{ actor.penisLengthMetric }} cm</span>
<span class="bio-segment">{{ actor.penisLengthImperial }}"</span>
</template>
</span>
</li>
<li
v-if="actor.height"
class="bio-item height"
@ -556,15 +582,22 @@ export default {
}
.height-imperial,
.weight-imperial {
.weight-imperial,
.penis-girth-imperial,
.penis-length-imperial,
.bio-segment {
padding: 0 0 0 .5rem;
border-left: solid 1px var(--lighten-weak);
margin: 0 0 0 .5rem;
}
.enhanced.icon {
.enhanced.icon,
.circumcised.icon {
fill: var(--primary);
padding: 0 .5rem;
}
.enhanced.icon {
transform: scaleX(-1);
}

View File

@ -97,6 +97,7 @@ async function mounted() {
'anal-creampie',
'oral-creampie',
'bukkake',
'fake-cum',
],
toys: [
'toy-anal',

View File

@ -0,0 +1,6 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>circles2</title>
<path d="M8 1c-3.866 0-7 3.134-7 7s3.134 7 7 7 7-3.134 7-7-3.134-7-7-7zM8 13c-2.761 0-5-2.239-5-5s2.239-5 5-5 5 2.239 5 5-2.239 5-5 5z"></path>
<path d="M8 5.25c1.516 0 2.75 1.234 2.75 2.75s-1.234 2.75-2.75 2.75-2.75-1.234-2.75-2.75 1.234-2.75 2.75-2.75zM8 4.25c-2.071 0-3.75 1.679-3.75 3.75s1.679 3.75 3.75 3.75c2.071 0 3.75-1.679 3.75-3.75s-1.679-3.75-3.75-3.75v0z"></path>
</svg>

After

Width:  |  Height:  |  Size: 538 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>crop</title>
<path d="M13 4l3-3-1-1-3 3h-7v-3h-2v3h-3v2h3v8h8v3h2v-3h3v-2h-3v-7zM5 5h5l-5 5v-5zM6 11l5-5v5h-5z"></path>
</svg>

After

Width:  |  Height:  |  Size: 265 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>height2</title>
<path d="M14 12h2l-2.5 3-2.5-3h2v-8h-2l2.5-3 2.5 3h-2zM8 3h-6v10h6v-10zM10 1v0 14h-10v-14h10z"></path>
</svg>

After

Width:  |  Height:  |  Size: 264 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>highlight</title>
<path d="M10.5 1.503l3.747 3.247 0.003-0.003-3.25-3.745 3.749 3.246 0.751 0.751-5.256 5.256c-0.463 0.463-1.174 0.534-1.714 0.214l0.719-0.722-3.25-3.745 3.747 3.247 0.003-0.003-3.25-3.745 3.747 3.247 0.003-0.003-3.25-3.745 3.747 3.247 0.003-0.003-3.25-3.745 3.747 3.247 0.003-0.003-3.25-3.745 3.747 3.247 0.003-0.003-3.25-3.745 3.747 3.247 0.003-0.003-3.25-3.745 3.747 3.247 0.003-0.003-3.25-3.745 3.747 3.247 0.003-0.003-3.25-3.745 3.747 3.247 0.003-0.003-3.25-3.745zM11.251 0.751l-6.221 6.218c-0.131-0.221-0.196-0.47-0.196-0.719 0-0.36 0.137-0.721 0.41-0.994l5.256-5.256 0.751 0.751zM5.031 6.969l3.5 3.5-2.531 2.531h-6v-1z"></path>
</svg>

After

Width:  |  Height:  |  Size: 796 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>page-break</title>
<path d="M0 8h2v1h-2zM3 8h3v1h-3zM7 8h2v1h-2zM10 8h3v1h-3zM14 8h2v1h-2zM13.75 0l0.25 7h-12l0.25-7h1.5l0.25 6h8l0.25-6zM2.25 16l-0.25-6h12l-0.25 6h-1.5l-0.25-4h-8l-0.25 4z"></path>
</svg>

After

Width:  |  Height:  |  Size: 344 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>page-break2</title>
<path d="M0 8h2v1h-2zM3 8h3v1h-3zM7 8h2v1h-2zM10 8h3v1h-3zM14 8h2v1h-2zM13.75 0l0.25 7h-12l0.25-7h0.5l0.25 6h10l0.25-6zM2.25 16l-0.25-6h12l-0.25 6h-0.5l-0.25-5h-10l-0.25 5z"></path>
</svg>

After

Width:  |  Height:  |  Size: 347 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>radio-unchecked</title>
<path d="M8 0c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zM8 14c-3.314 0-6-2.686-6-6s2.686-6 6-6c3.314 0 6 2.686 6 6s-2.686 6-6 6z"></path>
</svg>

After

Width:  |  Height:  |  Size: 322 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>rulers</title>
<path d="M8 2v-2h-6v2h-2v6h2v8h6v-8h8v-6h-8zM2 7h-1v-4h1v4zM7 2h-2v1h2v1h-2v1h2v1h-2v1h2v1h-2v1h2v1h-2v1h2v1h-2v1h2v2h-4v-14h4v1zM15 7h-1v-2h-1v2h-1v-2h-1v2h-1v-2h-1v2h-1v-4h7v4z"></path>
</svg>

After

Width:  |  Height:  |  Size: 348 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>scissors3</title>
<path d="M14.279 10.62c-1.042-1.628-2.829-2.345-3.992-1.601-0.1 0.064-0.193 0.138-0.277 0.218l-1.241-1.942 2.867-4.5c0.235-0.433 0.321-0.949 0.207-1.468-0.109-0.496-0.383-0.913-0.752-1.207l-0.192-0.122-3.398 5.314-3.398-5.314-0.192 0.122c-0.369 0.294-0.643 0.711-0.752 1.207-0.114 0.519-0.027 1.035 0.207 1.468l2.867 4.5-1.241 1.942c-0.085-0.081-0.177-0.154-0.277-0.218-1.163-0.744-2.95-0.028-3.992 1.601s-0.944 3.551 0.219 4.296c1.163 0.744 2.95 0.028 3.992-1.601l2.567-4.029 2.567 4.029c1.042 1.628 2.829 2.345 3.992 1.601s1.261-2.667 0.219-4.296zM3.67 12.507c-0.469 0.733-1.071 1.089-1.478 1.179-0 0-0 0-0 0-0.133 0.029-0.317 0.047-0.443-0.033-0.139-0.089-0.231-0.324-0.247-0.629-0.025-0.494 0.151-1.076 0.483-1.594 0.469-0.733 1.071-1.089 1.478-1.179 0.133-0.029 0.317-0.047 0.443 0.033 0.139 0.089 0.231 0.324 0.247 0.629 0.025 0.495-0.151 1.076-0.483 1.594zM7.5 8c-0.276 0-0.5-0.224-0.5-0.5s0.224-0.5 0.5-0.5 0.5 0.224 0.5 0.5-0.224 0.5-0.5 0.5zM13.498 13.023c-0.016 0.305-0.108 0.54-0.247 0.629-0.125 0.080-0.31 0.062-0.443 0.033 0 0 0 0-0 0-0.407-0.089-1.009-0.446-1.478-1.179-0.332-0.519-0.508-1.1-0.483-1.594 0.016-0.305 0.108-0.54 0.247-0.629 0.125-0.080 0.31-0.062 0.443-0.033 0.407 0.089 1.009 0.446 1.478 1.179 0.332 0.519 0.508 1.1 0.483 1.594z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>spinner11</title>
<path d="M16 6h-6l2.243-2.243c-1.133-1.133-2.64-1.757-4.243-1.757s-3.109 0.624-4.243 1.757c-1.133 1.133-1.757 2.64-1.757 4.243s0.624 3.109 1.757 4.243c1.133 1.133 2.64 1.757 4.243 1.757s3.109-0.624 4.243-1.757c0.095-0.095 0.185-0.192 0.273-0.292l1.505 1.317c-1.466 1.674-3.62 2.732-6.020 2.732-4.418 0-8-3.582-8-8s3.582-8 8-8c2.209 0 4.209 0.896 5.656 2.344l2.343-2.344v6z"></path>
</svg>

After

Width:  |  Height:  |  Size: 545 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>target</title>
<path d="M8 0c-4.411 0-8 3.589-8 8s3.589 8 8 8c4.411 0 8-3.589 8-8s-3.589-8-8-8zM8 14.222c-3.431 0-6.222-2.791-6.222-6.222s2.791-6.222 6.222-6.222 6.222 2.791 6.222 6.222c0 3.431-2.791 6.222-6.222 6.222zM8 3.556c-2.451 0-4.444 1.994-4.444 4.444s1.994 4.444 4.444 4.444 4.444-1.994 4.444-4.444c0-2.451-1.994-4.444-4.444-4.444zM8 10.667c-1.471 0-2.667-1.196-2.667-2.667s1.196-2.667 2.667-2.667c1.47 0 2.667 1.196 2.667 2.667s-1.196 2.667-2.667 2.667zM7 8c0-0.552 0.448-1 1-1s1 0.448 1 1c0 0.552-0.448 1-1 1s-1-0.448-1-1z"></path>
</svg>

After

Width:  |  Height:  |  Size: 688 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>target2</title>
<path d="M16 7h-1.577c-0.432-2.785-2.638-4.991-5.423-5.423v-1.577h-2v1.577c-2.785 0.432-4.991 2.638-5.423 5.423h-1.577v2h1.577c0.432 2.785 2.638 4.991 5.423 5.423v1.577h2v-1.577c2.785-0.432 4.991-2.638 5.423-5.423h1.577v-2zM12.388 7h-1.559c-0.301-0.852-0.977-1.528-1.829-1.829v-1.559c1.68 0.383 3.005 1.708 3.388 3.388zM8 9c-0.552 0-1-0.448-1-1s0.448-1 1-1c0.552 0 1 0.448 1 1s-0.448 1-1 1zM7 3.612v1.559c-0.852 0.301-1.528 0.977-1.829 1.829h-1.559c0.383-1.68 1.708-3.005 3.388-3.388zM3.612 9h1.559c0.301 0.852 0.977 1.528 1.829 1.829v1.559c-1.68-0.383-3.005-1.708-3.388-3.388zM9 12.388v-1.559c0.852-0.301 1.528-0.977 1.829-1.829h1.559c-0.383 1.68-1.708 3.005-3.388 3.388z"></path>
</svg>

After

Width:  |  Height:  |  Size: 843 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>target3</title>
<path d="M8 0c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zM12.243 12.243c-0.894 0.894-2.020 1.471-3.243 1.675v-2.917h-2v2.917c-1.222-0.204-2.349-0.781-3.243-1.675s-1.471-2.020-1.675-3.243h2.917v-2h-2.917c0.204-1.222 0.781-2.349 1.675-3.243s2.020-1.471 3.243-1.675v2.917h2v-2.917c1.222 0.204 2.349 0.781 3.243 1.675s1.471 2.020 1.675 3.243h-2.917v2h2.917c-0.204 1.222-0.781 2.349-1.675 3.243z"></path>
</svg>

After

Width:  |  Height:  |  Size: 575 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>tree</title>
<path d="M13.887 13.182l-2.387-3.182h1c0 0 0.001 0 0.001 0 0.276 0 0.5-0.224 0.5-0.5 0-0.121-0.043-0.231-0.114-0.318l-2.387-3.182h1c0.192 0 0.367-0.11 0.451-0.283s0.060-0.379-0.060-0.529l-4-5c-0.095-0.119-0.239-0.188-0.39-0.188s-0.296 0.069-0.39 0.188l-4 5c-0.12 0.15-0.143 0.356-0.060 0.529s0.258 0.283 0.451 0.283h1l-2.4 3.2c-0.114 0.152-0.132 0.354-0.047 0.524s0.258 0.276 0.447 0.276h1l-2.4 3.2c-0.114 0.152-0.132 0.354-0.047 0.524s0.258 0.276 0.447 0.276h4.5v1.5c0 0.276 0.224 0.5 0.5 0.5h2c0.276 0 0.5-0.224 0.5-0.5v-1.5h4.5c0 0 0 0 0.001 0 0.276 0 0.5-0.224 0.5-0.5 0-0.121-0.043-0.231-0.114-0.318z"></path>
</svg>

After

Width:  |  Height:  |  Size: 773 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>width</title>
<path d="M4 14v2l-3-2.5 3-2.5v2h8v-2l3 2.5-3 2.5v-2zM13 3h-10v5h10v-5zM15 1v0 9h-14v-9h14z"></path>
</svg>

After

Width:  |  Height:  |  Size: 259 B

View File

@ -45,6 +45,11 @@ function initActorActions(store, router) {
waist
hip
naturalBoobs
penisLengthMetric: penisLength(units:METRIC)
penisLengthImperial: penisLength(units:IMPERIAL)
penisGirthMetric: penisGirth(units:METRIC)
penisGirthImperial: penisGirth(units:IMPERIAL)
circumcised
heightMetric: height(units:METRIC)
heightImperial: height(units:IMPERIAL)
weightMetric: weight(units:METRIC)

View File

@ -278,6 +278,7 @@ exports.up = knex => Promise.resolve()
table.integer('penis_length', 3);
table.integer('penis_girth', 3);
table.boolean('circumcised');
table.integer('height', 3);
table.integer('weight', 3);
@ -355,6 +356,7 @@ exports.up = knex => Promise.resolve()
table.integer('penis_length', 3);
table.integer('penis_girth', 3);
table.boolean('circumcised');
table.integer('height', 3);
table.integer('weight', 3);
@ -1144,6 +1146,8 @@ exports.up = knex => Promise.resolve()
return knex.raw(`
COMMENT ON COLUMN actors.height IS E'@omit read,update,create,delete,all,many';
COMMENT ON COLUMN actors.weight IS E'@omit read,update,create,delete,all,many';
COMMENT ON COLUMN actors.penis_length IS E'@omit read,update,create,delete,all,many';
COMMENT ON COLUMN actors.penis_girth IS E'@omit read,update,create,delete,all,many';
COMMENT ON FUNCTION actors_tags IS E'@sortable';
COMMENT ON FUNCTION actors_channels IS E'@sortable';

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -3066,9 +3066,6 @@ const sites = [
url: 'https://seehimfuck.com',
tags: ['male-focus'],
parent: 'hussiepass',
parameters: {
tour: true,
},
},
{
slug: 'interracialpovs',
@ -3076,9 +3073,6 @@ const sites = [
url: 'https://www.interracialpovs.com',
tags: ['interracial', 'pov'],
parent: 'hussiepass',
parameters: {
tour: true,
},
},
{
slug: 'povpornstars',
@ -3089,7 +3083,6 @@ const sites = [
parameters: {
latest: 'http://www.povpornstars.com/tour/categories/movies_%d_d.html',
profile: 'http://www.povpornstars.com/tour/models/%s.html',
tour: true,
},
},
// HUSH PASS
@ -3176,7 +3169,7 @@ const sites = [
url: 'https://suburbansexparty.com',
parent: 'hushpass',
parameters: {
latest: 'https://hushpass.com/t1/categories/suburban-sex-party_%_d.html',
latest: 'https://hushpass.com/t1/categories/suburban-sex-party_%d_d.html',
media: 'https://hushpass.com',
t1: true,
},

View File

@ -627,6 +627,7 @@ const tagPosters = [
['facefucking', 5, 'Mia Moore B for Throated'],
['facial', 0, 'Brooklyn Gray in "All About Ass 4" for Evil Angel'],
['fake-boobs', 14, 'Rikki Six for Dream Dolls'],
['fake-cum', 2, 'Mimi Allen for Fucked Up Facials'],
['family', 0, 'Teanna Trump in "A Family Appear: Part One" for Brazzers'],
['femdom', 0, 'Alina Li in "Asian Domination… She Holds Jules Jordan\'s Cock Hostage!" for Jules Jordan'],
['fingering', 1, 'Marry Queen for Babespotting.tv'],
@ -634,7 +635,7 @@ const tagPosters = [
['gangbang', 5, 'Carter Cruise\'s first gangbang in "Slut Puppies 9" for Jules Jordan'],
['gaping', 1, 'Vina Sky in "Vina Sky Does Anal" for HardX'],
['indian', 0, 'Resha in "Casting Resha" for Watch 4 Beauty'],
['interracial', 0, 'Jaye Summers and Prince Yahshua in "Platinum Pussy 3" for Jules Jordan'],
['interracial', 1, 'Caprice and Valerie in "Sexual Attraction" for Hegre'],
['latina', 3, 'Gina Valentina for Brazzers'],
['lesbian', 0, 'Jenna Sativa and Alina Lopez in "Opposites Attract" for Girl Girl'],
['maid', 0, 'Whitney Wright in "Dredd Up Your Ass 2" for Jules Jordan'],
@ -731,6 +732,7 @@ const tagPhotos = [
// ['dap', 8, 'Lady Gang in SZ2478 LegalPorno'],
['dap', 'poster', 'Haley Reed in "Young Hot Ass" for Evil Angel'],
['dap', 0, 'Nicole Black doing double anal during a gangbang in GIO971 for LegalPorno'],
['deepthroat', 3, 'Kira Noir in "Ebony Throat Vs Monster Cock" for Throated'],
['deepthroat', 1, 'Jynx Maze in "Slutty and Sluttier 13" for Evil Angel'],
['deepthroat', 0, 'Chanel Grey in "Deepthroating Is Fun" for Throated'],
['double-blowjob', 0, 'Kira Noir and Kali Roses for Brazzers'],
@ -798,6 +800,8 @@ const tagPhotos = [
// ['fake-boobs', 6, 'Cathy Heaven in "Heavenly Ass" for Big Wett Butts'],
['fake-boobs', 7, 'Madison Ivy for Baby Got Boobs (Brazzers)'],
['fake-boobs', 12, 'Nikki Monroe and Kortney Kane for Big Tits In Uniform'],
['fake-cum', 0, 'Jynx Maze for Cumshot Surprise (Porn Pros)'],
['fake-cum', 1, 'Ricki White for Fucked Up Facials'],
['fingering', 2, 'Kylie Page and Hadley Viscara in "Busty Blonde Bombshells" for LesbianX'],
['fingering', 0, 'Ashly Anderson in "Rough Love" for Hookup Hotshot'],
['gangbang', 'poster', 'Kristen Scott in "Interracial Gangbang!" for Jules Jordan'],
@ -808,6 +812,7 @@ const tagPhotos = [
['gaping', 'poster', 'Zoey Monroe in "Manuel DPs Them All 5" for Jules Jordan'],
['gaping', 3, 'Jessyka Swan for 21Sextury'],
['gaping', 2, 'Alex Grey in "DP Masters 5" for Jules Jordan'],
['interracial', 0, 'Jaye Summers and Prince Yahshua in "Platinum Pussy 3" for Jules Jordan'],
['latina', 2, 'Veronica Leal for Her Limit'],
['latina', 1, 'Jynx Maze in "Big Anal Asses 2" for HardX'],
['latina', 0, 'Vienna Black for Spizoo'],

View File

@ -180,6 +180,9 @@ function curateActor(actor, withDetails = false, isProfile = false) {
waist: actor.waist,
hip: actor.hip,
naturalBoobs: actor.natural_boobs,
penisLength: actor.penis_length,
penisGirth: actor.penis_girth,
circumcised: actor.circumcised,
height: actor.height,
weight: actor.weight,
eyes: actor.eyes,
@ -262,6 +265,9 @@ function curateProfileEntry(profile) {
bust: profile.bust,
waist: profile.waist,
hip: profile.hip,
penis_length: profile.penisLength,
penis_girth: profile.penisGirth,
circumcised: profile.circumcised,
natural_boobs: profile.naturalBoobs,
height: profile.height,
weight: profile.weight,
@ -323,16 +329,35 @@ async function curateProfile(profile) {
curatedProfile.dateOfDeath = Number.isNaN(Number(profile.dateOfDeath)) ? null : profile.dateOfDeath;
curatedProfile.height = Number(profile.height) || profile.height?.match?.(/\d+/)?.[0] || null;
curatedProfile.weight = Number(profile.weight) || profile.weight?.match?.(/\d+/)?.[0] || null;
curatedProfile.cup = profile.cup || (typeof profile.bust === 'string' && profile.bust?.match?.(/[a-zA-Z]+/)?.[0]) || null;
curatedProfile.bust = Number(profile.bust) || profile.bust?.match?.(/\d+/)?.[0] || null;
curatedProfile.waist = Number(profile.waist) || profile.waist?.match?.(/\d+/)?.[0] || null;
curatedProfile.hip = Number(profile.hip) || profile.hip?.match?.(/\d+/)?.[0] || null;
curatedProfile.height = Number(profile.height) || profile.height?.match?.(/\d+/)?.[0] || null;
curatedProfile.weight = Number(profile.weight) || profile.weight?.match?.(/\d+/)?.[0] || null;
curatedProfile.penisLength = Number(profile.penisLength) || profile.penisLength?.match?.(/\d+/)?.[0] || null;
curatedProfile.penisGirth = Number(profile.penisGirth) || profile.penisGirth?.match?.(/\d+/)?.[0] || null;
curatedProfile.naturalBoobs = typeof profile.naturalBoobs === 'boolean' ? profile.naturalBoobs : null;
curatedProfile.hasTattoos = typeof profile.hasTattoos === 'boolean' ? profile.hasTattoos : null;
curatedProfile.hasPiercings = typeof profile.hasPiercings === 'boolean' ? profile.hasPiercings : null;
curatedProfile.circumcised = (typeof profile.circumcised === 'boolean' && profile.circumcised)
|| (/yes/i.test(profile.circumcised) && true)
|| (/no/i.test(profile.circumcised) && false)
|| null;
curatedProfile.naturalBoobs = (typeof profile.naturalBoobs === 'boolean' && profile.naturalBoobs)
|| (/yes/i.test(profile.naturalBoobs) && true)
|| (/no/i.test(profile.naturalBoobs) && false)
|| null;
curatedProfile.hasTattoos = (typeof profile.hasTattoos === 'boolean' && profile.hasTattoos)
|| (/yes/i.test(profile.hasTattoos) && true)
|| (/no/i.test(profile.hasTattoos) && true)
|| null;
curatedProfile.hasPiercings = (typeof profile.hasPiercings === 'boolean' && profile.hasPiercings)
|| (/yes/i.test(profile.hasPiercings) && true)
|| (/no/i.test(profile.hasPiercings) && true)
|| null;
if (argv.resolvePlace) {
const [placeOfBirth, placeOfResidence] = await Promise.all([
@ -437,6 +462,9 @@ async function interpolateProfiles(actorIds) {
'bust',
'waist',
'hip',
'penis_length',
'penis_girth',
'circumcised',
'natural_boobs',
'height',
'hair_color',

View File

@ -2,11 +2,17 @@
const util = require('util');
const { get, geta, ed, formatDate, ctxa } = require('../utils/q');
const { get, getAll, ed, formatDate, prefixUrl, ctxa } = require('../utils/q');
const slugify = require('../utils/slugify');
const { feetInchesToCm } = require('../utils/convert');
const { feetInchesToCm, inchesToCm } = require('../utils/convert');
function deriveEntryId(release) {
if (release.date && release.url) {
const slug = new URL(release.url).pathname.match(/\/trailers\/(.*).html/)[1];
return `${slugify(formatDate(release.date, 'YYYY-MM-DD'))}-${slugify(slug)}`;
}
if (release.date && release.title) {
return `${slugify(formatDate(release.date, 'YYYY-MM-DD'))}-${slugify(release.title)}`;
}
@ -50,21 +56,25 @@ function getImageWithFallbacks(q, selector, site, el) {
return sources.filter(Boolean).map(src => `${site.parameters?.media || site.url}${src}`);
}
function scrapeAll(scenes, site) {
return scenes.map(({ qu }) => {
function scrapeAll(scenes, channel) {
return scenes.map(({ query }) => {
const release = {};
release.title = qu.q('h3 a', 'title') || qu.q('h3 a', true);
release.url = qu.url('h3 a');
release.title = query.q('h4 a', true);
release.url = query.url('a');
release.date = qu.date('.modeldata p', 'YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/);
release.duration = qu.dur('.modeldata p');
release.date = query.date('.date', 'YYYY-MM-DD');
release.duration = query.duration('.time');
if (/bts|behind the scenes/i.test(release.title)) release.tags = ['behind the scenes'];
const count = query.number('a img', null, 'cnt');
release.poster = getImageWithFallbacks(qu.q, '.modelimg img', site);
[release.poster, ...release.photos] = Array.from({ length: count }, (value, index) => [
query.img('a img', `src${index}_3x`, { origin: channel.url }),
query.img('a img', `src${index}_2x`, { origin: channel.url }),
query.img('a img', `src${index}_1x`, { origin: channel.url }),
]);
// release.entryId = q('.modelimg img', 'id').match(/set-target-(\d+)/)[1];
release.stars = query.count('img[src*="star_full"]') + (query.count('img[src*="star_half"]') * 0.5);
release.entryId = deriveEntryId(release);
return release;
@ -107,45 +117,37 @@ function scrapeAllT1(scenes, site, accNetworkReleases) {
}).filter(Boolean);
}
function scrapeAllTour(scenes) {
return scenes.map(({ qu }) => {
const release = {};
function scrapeScene({ html, query }, channel, url) {
const release = { url }; // url used for entry ID
release.title = qu.q('h4 a', true);
release.url = qu.url('a');
release.date = qu.date('.tour_update_models + span', 'YYYY-MM-DD');
release.title = query.cnt('.videoDetails h3');
release.description = query.cnt('.videoDetails p');
release.actors = qu.all('.tour_update_models a', true);
release.date = query.date('.videoInfo p', ['MM/DD/YYYY', 'YYYY-MM-DD']);
release.duration = Number(query.cnt('.videoInfo p:nth-of-type(2)')?.match(/(\d+) min/i)?.[1]) * 60;
release.poster = qu.img('a img');
release.entryId = deriveEntryId(release);
return release;
});
}
function scrapeScene({ html, qu }, site, url, baseRelease) {
const release = { url };
release.title = qu.q('.centerwrap h2', true);
release.description = qu.q('.videocontent p', true);
release.date = qu.date('.videodetails .date', ['MM/DD/YYYY', 'YYYY-MM-DD']);
release.duration = qu.dur('.videodetails .date');
release.actors = qu.all('.modelname a', true);
release.actors = query.cnts('.update_models a');
const posterPath = html.match(/poster="([\w-/.]+)"/)?.[1];
[release.poster, release.photos] = extractPoster(posterPath, site, baseRelease);
const poster = prefixUrl(posterPath, channel.url);
[release.poster, ...release.photos] = [poster, ...query.imgs('.item-thumb img', 'src0_1x', { origin: channel.url })]
.map(src => [
src.replace('-1x', '-3x'),
src.replace('-1x', '-2x'),
src,
]);
const trailerPath = html.match(/\/trailers\/.*.mp4/);
if (trailerPath) release.trailer = { src: `${site.parameters?.media || site.url}${trailerPath}` };
const stars = qu.q('.modelrates + p', true).match(/\d.\d/)?.[0];
if (stars) release.stars = Number(stars);
if (trailerPath) {
// release.trailer = { src: `${channel.parameters?.media || channel.url}${trailerPath}` };
release.trailer = prefixUrl(trailerPath, channel.parameters?.media || channel.url);
}
release.tags = query.cnts('.featuring a[href*="categories/"]');
release.stars = query.count('.stars img[src*="star_full"]') + (query.count('.stars img[src*="star_half"]') * 0.5);
// release.entryId = html.match(/set-target-(\d+)/)[1];
release.entryId = deriveEntryId(release);
return release;
@ -193,64 +195,6 @@ function scrapeSceneT1({ html, qu }, site, url, baseRelease) {
return release;
}
function scrapeSceneTour({ html, qu }, site, url) {
const release = {};
if (url) release.url = url;
release.title = qu.q('.update_title, .video-title', true);
release.description = qu.q('.latest_update_description, .video-summary', true);
const date = qu.date('.availdate, .update_date', 'YYYY-MM-DD');
if (date) release.date = date;
release.actors = qu.all('.update_block_info .tour_update_models a, .video-model .tour_update_models a', true);
release.tags = qu.all('.update_tags a, .tour_update_tags a', true);
const [photo, poster, ...photos] = qu.imgs('.update_image img:not(.play_icon_overlay)');
if (poster || photo) release.poster = poster || photo;
if ((photo && poster) || photos) release.photos = poster ? [photo, ...photos] : photos; // don't use first photo when already used as fallback poster
if (release.date) release.entryId = deriveEntryId(release);
const trailerCode = qu.q('.update_image a', 'onclick');
const trailerPath = trailerCode?.match(/tload\('(.*)'\)/)?.[1] || html.match(/\/trailer\/.*\.mp4/)?.[0];
if (trailerPath && /^http/.test(trailerPath)) release.trailer = { src: trailerPath };
else if (trailerPath) release.trailer = { src: `${site.parameters?.media || site.url}${trailerPath}` };
return release;
}
function scrapeProfile({ el, qu }, site) {
const profile = {};
const bio = qu.texts('.stats p').reduce((acc, info) => {
const [key, value] = info.split(':');
return {
...acc,
[slugify(key, '_')]: value.trim(),
};
}, {});
if (bio.measurements) {
const [bust, waist, hip] = bio.measurements.split('-');
if (bust) profile.bust = bust;
if (waist) profile.waist = Number(waist);
if (hip) profile.hip = Number(hip);
}
if (bio.age) profile.age = Number(bio.age);
if (bio.height) profile.height = feetInchesToCm(bio.height);
profile.avatar = getImageWithFallbacks(qu.q, '.profileimg img', site);
const qReleases = ctxa(el, '.modelFeatures .modelfeature');
profile.releases = scrapeAll(qReleases, site);
return profile;
}
function scrapeProfileT1({ el, qu }, site) {
const profile = {};
@ -289,15 +233,16 @@ function scrapeProfileT1({ el, qu }, site) {
return profile;
}
function scrapeProfileTour({ el, qu }, site) {
function scrapeProfile({ query }, channel) {
const profile = {};
const bio = qu.texts('.model_bio').reduce((acc, info) => {
const [key, value] = info.split(':');
const bio = query.all('.stats li').reduce((acc, bioEl) => {
const key = query.cnt(bioEl, 'strong');
const value = query.url(bioEl) || query.text(bioEl);
return {
...acc,
[slugify(key, '_')]: value.trim(),
[slugify(key, '_')]: value,
};
}, {});
@ -318,6 +263,11 @@ function scrapeProfileTour({ el, qu }, site) {
if (hip) profile.hip = Number(hip);
}
if (bio.penis_length) profile.penisLength = Number(bio.penis_length.match(/(\d+)\s*cm/i)?.[1] || inchesToCm(bio.penis_length.match(/(\d+\.?\d+)\s*in/i)?.[1])) || null;
if (bio.penis_girth) profile.penisGirth = Number(bio.penis_girth.match(/(\d+)\s*cm/i)?.[1] || inchesToCm(bio.penis_girth.match(/(\d+\.?\d+)\s*in/i)?.[1])) || null;
if (bio.circumcised && /yes/i.test(bio.circumcised)) profile.circumcised = true;
if (bio.circumcised && /no/i.test(bio.circumcised)) profile.circumcised = false;
if (bio.natural_breasts && /yes/i.test(bio.natural_breasts)) profile.naturalBoobs = true;
if (bio.natural_breasts && /no/i.test(bio.natural_breasts)) profile.naturalBoobs = false;
@ -328,33 +278,31 @@ function scrapeProfileTour({ el, qu }, site) {
if (bio.aliases) profile.aliases = bio.aliases.split(',').map(alias => alias.trim());
profile.avatar = getImageWithFallbacks(qu.q, '.model_picture img', site);
profile.social = [bio.onlyfans, bio.twitter, bio.instagram].filter(Boolean);
const qReleases = ctxa(el, '.update_block');
profile.releases = qReleases.map((qRelease) => {
const url = qRelease.qu.url('.update_image a[href]');
const release = scrapeSceneTour(qRelease, site);
if (!/\/(signup|join)/i.test(url)) release.url = url;
release.entryId = deriveEntryId(release);
release.site = site;
return release;
});
profile.avatar = [
query.img('.profile-pic img', 'src0_3x', { origin: channel.url }),
query.img('.profile-pic img', 'src0_2x', { origin: channel.url }),
query.img('.profile-pic img', 'src0_1x', { origin: channel.url }),
];
return profile;
}
async function fetchLatest(site, page = 1, include, { uniqueReleases, duplicateReleases }) {
async function fetchLatest(site, page = 1, include, { uniqueReleases = [], duplicateReleases = [] }) {
const url = (site.parameters?.latest && util.format(site.parameters.latest, page))
|| (site.parameters?.t1 && `${site.url}/t1/categories/movies_${page}_d.html`)
|| `${site.url}/categories/movies_${page}_d.html`;
const res = await geta(url, '.modelfeature, .item-video, .updateItem');
const res = await getAll(url, '.modelfeature, .item-video, .updateItem');
if (!res.ok) return res.status;
if (site.parameters?.t1) return scrapeAllT1(res.items, site, [...uniqueReleases, ...duplicateReleases]);
if (site.parameters?.tour) return scrapeAllTour(res.items, site);
if (!res.ok) {
return res.status;
}
if (site.parameters?.t1) {
return scrapeAllT1(res.items, site, [...uniqueReleases, ...duplicateReleases]);
}
return scrapeAll(res.items, site, uniqueReleases);
}
@ -362,9 +310,13 @@ async function fetchLatest(site, page = 1, include, { uniqueReleases, duplicateR
async function fetchScene(url, site, baseRelease) {
const res = await get(url);
if (!res.ok) return res.status;
if (site.parameters?.t1) return scrapeSceneT1(res.item, site, url, baseRelease);
if (site.parameters?.tour) return scrapeSceneTour(res.item, site, url, baseRelease);
if (!res.ok) {
return res.status;
}
if (site.parameters?.t1) {
return scrapeSceneT1(res.item, site, url, baseRelease);
}
return scrapeScene(res.item, site, url, baseRelease);
}
@ -377,15 +329,19 @@ async function fetchProfile({ name: actorName }, { site }) {
const res1 = site.parameters?.profile
? await get(util.format(site.parameters.profile, actorSlugA))
: await get(`${site.url}/${t1}models/${actorSlugA}.html`);
: await get(`${site.url}/${t1}models/${actorSlugA}.html`, null, null, { followRedirects: false });
const res = (res1.ok && res1)
|| (site.parameters?.profile && await get(util.format(site.parameters.profile, actorSlugB)))
|| await get(`${site.url}/${t1}models/${actorSlugB}.html`);
|| await get(`${site.url}/${t1}models/${actorSlugB}.html`, null, null, { followRedirects: false });
if (!res.ok) return res.status;
if (site.parameters?.t1) return scrapeProfileT1(res.item, site);
if (site.parameters?.tour) return scrapeProfileTour(res.item, site);
if (!res.ok) {
return res.status;
}
if (site.parameters?.t1) {
return scrapeProfileT1(res.item, site);
}
return scrapeProfile(res.item, site);
}

View File

@ -26,6 +26,10 @@ function cmToFeetInches(centimeters) {
return { feet, inches };
}
function cmToInches(centimeters) {
return centimeters / 2.54;
}
function heightToCm(height) {
if (!height) return null;
@ -52,6 +56,7 @@ function kgToLbs(kgs) {
module.exports = {
cmToFeetInches,
cmToInches,
feetInchesToCm,
heightToCm,
inchesToCm,

View File

@ -2,7 +2,7 @@
const { makeExtendSchemaPlugin, gql } = require('graphile-utils');
const moment = require('moment');
const { cmToFeetInches, kgToLbs } = require('../../utils/convert');
const { cmToFeetInches, cmToInches, kgToLbs } = require('../../utils/convert');
const schemaExtender = makeExtendSchemaPlugin(_build => ({
typeDefs: gql`
@ -16,6 +16,8 @@ const schemaExtender = makeExtendSchemaPlugin(_build => ({
ageAtDeath: Int @requires(columns: ["dateOfBirth", "dateOfDeath"])
height(units:Units): String @requires(columns: ["height"])
weight(units:Units): String @requires(columns: ["weight"])
penisLength(units:Units): String @requires(columns: ["penis_length"])
penisGirth(units:Units): String @requires(columns: ["penis_girth"])
}
`,
resolvers: {
@ -47,6 +49,20 @@ const schemaExtender = makeExtendSchemaPlugin(_build => ({
? kgToLbs(parent.weight).toString()
: parent.weight.toString();
},
penisLength(parent, args, _context, _info) {
if (!parent.penisLength) return null;
return args.units === 'IMPERIAL'
? (Math.round(cmToInches(parent.penisLength) * 4) / 4).toString() // round to nearest quarter inch
: parent.penisLength.toString();
},
penisGirth(parent, args, _context, _info) {
if (!parent.penisGirth) return null;
return args.units === 'IMPERIAL'
? (Math.round(cmToInches(parent.penisGirth) * 4) / 4).toString() // round to nearest quarter inch
: parent.penisGirth.toString();
},
},
},
}));