Updated Hussie Pass scraper for new site design. Added cock size to profiles.
|
@ -166,6 +166,32 @@
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</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
|
<li
|
||||||
v-if="actor.height"
|
v-if="actor.height"
|
||||||
class="bio-item height"
|
class="bio-item height"
|
||||||
|
@ -556,15 +582,22 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.height-imperial,
|
.height-imperial,
|
||||||
.weight-imperial {
|
.weight-imperial,
|
||||||
|
.penis-girth-imperial,
|
||||||
|
.penis-length-imperial,
|
||||||
|
.bio-segment {
|
||||||
padding: 0 0 0 .5rem;
|
padding: 0 0 0 .5rem;
|
||||||
border-left: solid 1px var(--lighten-weak);
|
border-left: solid 1px var(--lighten-weak);
|
||||||
margin: 0 0 0 .5rem;
|
margin: 0 0 0 .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.enhanced.icon {
|
.enhanced.icon,
|
||||||
|
.circumcised.icon {
|
||||||
fill: var(--primary);
|
fill: var(--primary);
|
||||||
padding: 0 .5rem;
|
padding: 0 .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enhanced.icon {
|
||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,7 @@ async function mounted() {
|
||||||
'anal-creampie',
|
'anal-creampie',
|
||||||
'oral-creampie',
|
'oral-creampie',
|
||||||
'bukkake',
|
'bukkake',
|
||||||
|
'fake-cum',
|
||||||
],
|
],
|
||||||
toys: [
|
toys: [
|
||||||
'toy-anal',
|
'toy-anal',
|
||||||
|
|
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -45,6 +45,11 @@ function initActorActions(store, router) {
|
||||||
waist
|
waist
|
||||||
hip
|
hip
|
||||||
naturalBoobs
|
naturalBoobs
|
||||||
|
penisLengthMetric: penisLength(units:METRIC)
|
||||||
|
penisLengthImperial: penisLength(units:IMPERIAL)
|
||||||
|
penisGirthMetric: penisGirth(units:METRIC)
|
||||||
|
penisGirthImperial: penisGirth(units:IMPERIAL)
|
||||||
|
circumcised
|
||||||
heightMetric: height(units:METRIC)
|
heightMetric: height(units:METRIC)
|
||||||
heightImperial: height(units:IMPERIAL)
|
heightImperial: height(units:IMPERIAL)
|
||||||
weightMetric: weight(units:METRIC)
|
weightMetric: weight(units:METRIC)
|
||||||
|
|
|
@ -278,6 +278,7 @@ exports.up = knex => Promise.resolve()
|
||||||
|
|
||||||
table.integer('penis_length', 3);
|
table.integer('penis_length', 3);
|
||||||
table.integer('penis_girth', 3);
|
table.integer('penis_girth', 3);
|
||||||
|
table.boolean('circumcised');
|
||||||
|
|
||||||
table.integer('height', 3);
|
table.integer('height', 3);
|
||||||
table.integer('weight', 3);
|
table.integer('weight', 3);
|
||||||
|
@ -355,6 +356,7 @@ exports.up = knex => Promise.resolve()
|
||||||
|
|
||||||
table.integer('penis_length', 3);
|
table.integer('penis_length', 3);
|
||||||
table.integer('penis_girth', 3);
|
table.integer('penis_girth', 3);
|
||||||
|
table.boolean('circumcised');
|
||||||
|
|
||||||
table.integer('height', 3);
|
table.integer('height', 3);
|
||||||
table.integer('weight', 3);
|
table.integer('weight', 3);
|
||||||
|
@ -1144,6 +1146,8 @@ exports.up = knex => Promise.resolve()
|
||||||
return knex.raw(`
|
return knex.raw(`
|
||||||
COMMENT ON COLUMN actors.height IS E'@omit read,update,create,delete,all,many';
|
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.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_tags IS E'@sortable';
|
||||||
COMMENT ON FUNCTION actors_channels IS E'@sortable';
|
COMMENT ON FUNCTION actors_channels IS E'@sortable';
|
||||||
|
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 563 B After Width: | Height: | Size: 563 B |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 264 KiB |
After Width: | Height: | Size: 382 KiB |
After Width: | Height: | Size: 405 KiB |
After Width: | Height: | Size: 418 KiB |
After Width: | Height: | Size: 498 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 8.5 MiB |
After Width: | Height: | Size: 10 MiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 23 KiB |
|
@ -3066,9 +3066,6 @@ const sites = [
|
||||||
url: 'https://seehimfuck.com',
|
url: 'https://seehimfuck.com',
|
||||||
tags: ['male-focus'],
|
tags: ['male-focus'],
|
||||||
parent: 'hussiepass',
|
parent: 'hussiepass',
|
||||||
parameters: {
|
|
||||||
tour: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'interracialpovs',
|
slug: 'interracialpovs',
|
||||||
|
@ -3076,9 +3073,6 @@ const sites = [
|
||||||
url: 'https://www.interracialpovs.com',
|
url: 'https://www.interracialpovs.com',
|
||||||
tags: ['interracial', 'pov'],
|
tags: ['interracial', 'pov'],
|
||||||
parent: 'hussiepass',
|
parent: 'hussiepass',
|
||||||
parameters: {
|
|
||||||
tour: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'povpornstars',
|
slug: 'povpornstars',
|
||||||
|
@ -3089,7 +3083,6 @@ const sites = [
|
||||||
parameters: {
|
parameters: {
|
||||||
latest: 'http://www.povpornstars.com/tour/categories/movies_%d_d.html',
|
latest: 'http://www.povpornstars.com/tour/categories/movies_%d_d.html',
|
||||||
profile: 'http://www.povpornstars.com/tour/models/%s.html',
|
profile: 'http://www.povpornstars.com/tour/models/%s.html',
|
||||||
tour: true,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// HUSH PASS
|
// HUSH PASS
|
||||||
|
@ -3176,7 +3169,7 @@ const sites = [
|
||||||
url: 'https://suburbansexparty.com',
|
url: 'https://suburbansexparty.com',
|
||||||
parent: 'hushpass',
|
parent: 'hushpass',
|
||||||
parameters: {
|
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',
|
media: 'https://hushpass.com',
|
||||||
t1: true,
|
t1: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -627,6 +627,7 @@ const tagPosters = [
|
||||||
['facefucking', 5, 'Mia Moore B for Throated'],
|
['facefucking', 5, 'Mia Moore B for Throated'],
|
||||||
['facial', 0, 'Brooklyn Gray in "All About Ass 4" for Evil Angel'],
|
['facial', 0, 'Brooklyn Gray in "All About Ass 4" for Evil Angel'],
|
||||||
['fake-boobs', 14, 'Rikki Six for Dream Dolls'],
|
['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'],
|
['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'],
|
['femdom', 0, 'Alina Li in "Asian Domination… She Holds Jules Jordan\'s Cock Hostage!" for Jules Jordan'],
|
||||||
['fingering', 1, 'Marry Queen for Babespotting.tv'],
|
['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'],
|
['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'],
|
['gaping', 1, 'Vina Sky in "Vina Sky Does Anal" for HardX'],
|
||||||
['indian', 0, 'Resha in "Casting Resha" for Watch 4 Beauty'],
|
['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'],
|
['latina', 3, 'Gina Valentina for Brazzers'],
|
||||||
['lesbian', 0, 'Jenna Sativa and Alina Lopez in "Opposites Attract" for Girl Girl'],
|
['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'],
|
['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', 8, 'Lady Gang in SZ2478 LegalPorno'],
|
||||||
['dap', 'poster', 'Haley Reed in "Young Hot Ass" for Evil Angel'],
|
['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'],
|
['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', 1, 'Jynx Maze in "Slutty and Sluttier 13" for Evil Angel'],
|
||||||
['deepthroat', 0, 'Chanel Grey in "Deepthroating Is Fun" for Throated'],
|
['deepthroat', 0, 'Chanel Grey in "Deepthroating Is Fun" for Throated'],
|
||||||
['double-blowjob', 0, 'Kira Noir and Kali Roses for Brazzers'],
|
['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', 6, 'Cathy Heaven in "Heavenly Ass" for Big Wett Butts'],
|
||||||
['fake-boobs', 7, 'Madison Ivy for Baby Got Boobs (Brazzers)'],
|
['fake-boobs', 7, 'Madison Ivy for Baby Got Boobs (Brazzers)'],
|
||||||
['fake-boobs', 12, 'Nikki Monroe and Kortney Kane for Big Tits In Uniform'],
|
['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', 2, 'Kylie Page and Hadley Viscara in "Busty Blonde Bombshells" for LesbianX'],
|
||||||
['fingering', 0, 'Ashly Anderson in "Rough Love" for Hookup Hotshot'],
|
['fingering', 0, 'Ashly Anderson in "Rough Love" for Hookup Hotshot'],
|
||||||
['gangbang', 'poster', 'Kristen Scott in "Interracial Gangbang!" for Jules Jordan'],
|
['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', 'poster', 'Zoey Monroe in "Manuel DPs Them All 5" for Jules Jordan'],
|
||||||
['gaping', 3, 'Jessyka Swan for 21Sextury'],
|
['gaping', 3, 'Jessyka Swan for 21Sextury'],
|
||||||
['gaping', 2, 'Alex Grey in "DP Masters 5" for Jules Jordan'],
|
['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', 2, 'Veronica Leal for Her Limit'],
|
||||||
['latina', 1, 'Jynx Maze in "Big Anal Asses 2" for HardX'],
|
['latina', 1, 'Jynx Maze in "Big Anal Asses 2" for HardX'],
|
||||||
['latina', 0, 'Vienna Black for Spizoo'],
|
['latina', 0, 'Vienna Black for Spizoo'],
|
||||||
|
|
|
@ -180,6 +180,9 @@ function curateActor(actor, withDetails = false, isProfile = false) {
|
||||||
waist: actor.waist,
|
waist: actor.waist,
|
||||||
hip: actor.hip,
|
hip: actor.hip,
|
||||||
naturalBoobs: actor.natural_boobs,
|
naturalBoobs: actor.natural_boobs,
|
||||||
|
penisLength: actor.penis_length,
|
||||||
|
penisGirth: actor.penis_girth,
|
||||||
|
circumcised: actor.circumcised,
|
||||||
height: actor.height,
|
height: actor.height,
|
||||||
weight: actor.weight,
|
weight: actor.weight,
|
||||||
eyes: actor.eyes,
|
eyes: actor.eyes,
|
||||||
|
@ -262,6 +265,9 @@ function curateProfileEntry(profile) {
|
||||||
bust: profile.bust,
|
bust: profile.bust,
|
||||||
waist: profile.waist,
|
waist: profile.waist,
|
||||||
hip: profile.hip,
|
hip: profile.hip,
|
||||||
|
penis_length: profile.penisLength,
|
||||||
|
penis_girth: profile.penisGirth,
|
||||||
|
circumcised: profile.circumcised,
|
||||||
natural_boobs: profile.naturalBoobs,
|
natural_boobs: profile.naturalBoobs,
|
||||||
height: profile.height,
|
height: profile.height,
|
||||||
weight: profile.weight,
|
weight: profile.weight,
|
||||||
|
@ -323,16 +329,35 @@ async function curateProfile(profile) {
|
||||||
|
|
||||||
curatedProfile.dateOfDeath = Number.isNaN(Number(profile.dateOfDeath)) ? null : profile.dateOfDeath;
|
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.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.bust = Number(profile.bust) || profile.bust?.match?.(/\d+/)?.[0] || null;
|
||||||
curatedProfile.waist = Number(profile.waist) || profile.waist?.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.hip = Number(profile.hip) || profile.hip?.match?.(/\d+/)?.[0] || null;
|
||||||
curatedProfile.height = Number(profile.height) || profile.height?.match?.(/\d+/)?.[0] || null;
|
curatedProfile.penisLength = Number(profile.penisLength) || profile.penisLength?.match?.(/\d+/)?.[0] || null;
|
||||||
curatedProfile.weight = Number(profile.weight) || profile.weight?.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.circumcised = (typeof profile.circumcised === 'boolean' && profile.circumcised)
|
||||||
curatedProfile.hasTattoos = typeof profile.hasTattoos === 'boolean' ? profile.hasTattoos : null;
|
|| (/yes/i.test(profile.circumcised) && true)
|
||||||
curatedProfile.hasPiercings = typeof profile.hasPiercings === 'boolean' ? profile.hasPiercings : null;
|
|| (/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) {
|
if (argv.resolvePlace) {
|
||||||
const [placeOfBirth, placeOfResidence] = await Promise.all([
|
const [placeOfBirth, placeOfResidence] = await Promise.all([
|
||||||
|
@ -437,6 +462,9 @@ async function interpolateProfiles(actorIds) {
|
||||||
'bust',
|
'bust',
|
||||||
'waist',
|
'waist',
|
||||||
'hip',
|
'hip',
|
||||||
|
'penis_length',
|
||||||
|
'penis_girth',
|
||||||
|
'circumcised',
|
||||||
'natural_boobs',
|
'natural_boobs',
|
||||||
'height',
|
'height',
|
||||||
'hair_color',
|
'hair_color',
|
||||||
|
|
|
@ -2,11 +2,17 @@
|
||||||
|
|
||||||
const util = require('util');
|
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 slugify = require('../utils/slugify');
|
||||||
const { feetInchesToCm } = require('../utils/convert');
|
const { feetInchesToCm, inchesToCm } = require('../utils/convert');
|
||||||
|
|
||||||
function deriveEntryId(release) {
|
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) {
|
if (release.date && release.title) {
|
||||||
return `${slugify(formatDate(release.date, 'YYYY-MM-DD'))}-${slugify(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}`);
|
return sources.filter(Boolean).map(src => `${site.parameters?.media || site.url}${src}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeAll(scenes, site) {
|
function scrapeAll(scenes, channel) {
|
||||||
return scenes.map(({ qu }) => {
|
return scenes.map(({ query }) => {
|
||||||
const release = {};
|
const release = {};
|
||||||
|
|
||||||
release.title = qu.q('h3 a', 'title') || qu.q('h3 a', true);
|
release.title = query.q('h4 a', true);
|
||||||
release.url = qu.url('h3 a');
|
release.url = query.url('a');
|
||||||
|
|
||||||
release.date = qu.date('.modeldata p', 'YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/);
|
release.date = query.date('.date', 'YYYY-MM-DD');
|
||||||
release.duration = qu.dur('.modeldata p');
|
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);
|
release.entryId = deriveEntryId(release);
|
||||||
|
|
||||||
return release;
|
return release;
|
||||||
|
@ -107,45 +117,37 @@ function scrapeAllT1(scenes, site, accNetworkReleases) {
|
||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeAllTour(scenes) {
|
function scrapeScene({ html, query }, channel, url) {
|
||||||
return scenes.map(({ qu }) => {
|
const release = { url }; // url used for entry ID
|
||||||
const release = {};
|
|
||||||
|
|
||||||
release.title = qu.q('h4 a', true);
|
release.title = query.cnt('.videoDetails h3');
|
||||||
release.url = qu.url('a');
|
release.description = query.cnt('.videoDetails p');
|
||||||
release.date = qu.date('.tour_update_models + span', 'YYYY-MM-DD');
|
|
||||||
|
|
||||||
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.actors = query.cnts('.update_models a');
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
const posterPath = html.match(/poster="([\w-/.]+)"/)?.[1];
|
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/);
|
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 (trailerPath) {
|
||||||
if (stars) release.stars = Number(stars);
|
// 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);
|
release.entryId = deriveEntryId(release);
|
||||||
|
|
||||||
return release;
|
return release;
|
||||||
|
@ -193,64 +195,6 @@ function scrapeSceneT1({ html, qu }, site, url, baseRelease) {
|
||||||
return release;
|
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) {
|
function scrapeProfileT1({ el, qu }, site) {
|
||||||
const profile = {};
|
const profile = {};
|
||||||
|
|
||||||
|
@ -289,15 +233,16 @@ function scrapeProfileT1({ el, qu }, site) {
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeProfileTour({ el, qu }, site) {
|
function scrapeProfile({ query }, channel) {
|
||||||
const profile = {};
|
const profile = {};
|
||||||
|
|
||||||
const bio = qu.texts('.model_bio').reduce((acc, info) => {
|
const bio = query.all('.stats li').reduce((acc, bioEl) => {
|
||||||
const [key, value] = info.split(':');
|
const key = query.cnt(bioEl, 'strong');
|
||||||
|
const value = query.url(bioEl) || query.text(bioEl);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...acc,
|
...acc,
|
||||||
[slugify(key, '_')]: value.trim(),
|
[slugify(key, '_')]: value,
|
||||||
};
|
};
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
|
@ -318,6 +263,11 @@ function scrapeProfileTour({ el, qu }, site) {
|
||||||
if (hip) profile.hip = Number(hip);
|
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 && /yes/i.test(bio.natural_breasts)) profile.naturalBoobs = true;
|
||||||
if (bio.natural_breasts && /no/i.test(bio.natural_breasts)) profile.naturalBoobs = false;
|
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());
|
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.avatar = [
|
||||||
profile.releases = qReleases.map((qRelease) => {
|
query.img('.profile-pic img', 'src0_3x', { origin: channel.url }),
|
||||||
const url = qRelease.qu.url('.update_image a[href]');
|
query.img('.profile-pic img', 'src0_2x', { origin: channel.url }),
|
||||||
const release = scrapeSceneTour(qRelease, site);
|
query.img('.profile-pic img', 'src0_1x', { origin: channel.url }),
|
||||||
|
];
|
||||||
if (!/\/(signup|join)/i.test(url)) release.url = url;
|
|
||||||
release.entryId = deriveEntryId(release);
|
|
||||||
release.site = site;
|
|
||||||
|
|
||||||
return release;
|
|
||||||
});
|
|
||||||
|
|
||||||
return profile;
|
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))
|
const url = (site.parameters?.latest && util.format(site.parameters.latest, page))
|
||||||
|| (site.parameters?.t1 && `${site.url}/t1/categories/movies_${page}_d.html`)
|
|| (site.parameters?.t1 && `${site.url}/t1/categories/movies_${page}_d.html`)
|
||||||
|| `${site.url}/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 (!res.ok) {
|
||||||
if (site.parameters?.t1) return scrapeAllT1(res.items, site, [...uniqueReleases, ...duplicateReleases]);
|
return res.status;
|
||||||
if (site.parameters?.tour) return scrapeAllTour(res.items, site);
|
}
|
||||||
|
|
||||||
|
if (site.parameters?.t1) {
|
||||||
|
return scrapeAllT1(res.items, site, [...uniqueReleases, ...duplicateReleases]);
|
||||||
|
}
|
||||||
|
|
||||||
return scrapeAll(res.items, site, uniqueReleases);
|
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) {
|
async function fetchScene(url, site, baseRelease) {
|
||||||
const res = await get(url);
|
const res = await get(url);
|
||||||
|
|
||||||
if (!res.ok) return res.status;
|
if (!res.ok) {
|
||||||
if (site.parameters?.t1) return scrapeSceneT1(res.item, site, url, baseRelease);
|
return res.status;
|
||||||
if (site.parameters?.tour) return scrapeSceneTour(res.item, site, url, baseRelease);
|
}
|
||||||
|
|
||||||
|
if (site.parameters?.t1) {
|
||||||
|
return scrapeSceneT1(res.item, site, url, baseRelease);
|
||||||
|
}
|
||||||
|
|
||||||
return scrapeScene(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
|
const res1 = site.parameters?.profile
|
||||||
? await get(util.format(site.parameters.profile, actorSlugA))
|
? 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)
|
const res = (res1.ok && res1)
|
||||||
|| (site.parameters?.profile && await get(util.format(site.parameters.profile, actorSlugB)))
|
|| (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 (!res.ok) {
|
||||||
if (site.parameters?.t1) return scrapeProfileT1(res.item, site);
|
return res.status;
|
||||||
if (site.parameters?.tour) return scrapeProfileTour(res.item, site);
|
}
|
||||||
|
|
||||||
|
if (site.parameters?.t1) {
|
||||||
|
return scrapeProfileT1(res.item, site);
|
||||||
|
}
|
||||||
|
|
||||||
return scrapeProfile(res.item, site);
|
return scrapeProfile(res.item, site);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,10 @@ function cmToFeetInches(centimeters) {
|
||||||
return { feet, inches };
|
return { feet, inches };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cmToInches(centimeters) {
|
||||||
|
return centimeters / 2.54;
|
||||||
|
}
|
||||||
|
|
||||||
function heightToCm(height) {
|
function heightToCm(height) {
|
||||||
if (!height) return null;
|
if (!height) return null;
|
||||||
|
|
||||||
|
@ -52,6 +56,7 @@ function kgToLbs(kgs) {
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
cmToFeetInches,
|
cmToFeetInches,
|
||||||
|
cmToInches,
|
||||||
feetInchesToCm,
|
feetInchesToCm,
|
||||||
heightToCm,
|
heightToCm,
|
||||||
inchesToCm,
|
inchesToCm,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
const { makeExtendSchemaPlugin, gql } = require('graphile-utils');
|
const { makeExtendSchemaPlugin, gql } = require('graphile-utils');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const { cmToFeetInches, kgToLbs } = require('../../utils/convert');
|
const { cmToFeetInches, cmToInches, kgToLbs } = require('../../utils/convert');
|
||||||
|
|
||||||
const schemaExtender = makeExtendSchemaPlugin(_build => ({
|
const schemaExtender = makeExtendSchemaPlugin(_build => ({
|
||||||
typeDefs: gql`
|
typeDefs: gql`
|
||||||
|
@ -16,6 +16,8 @@ const schemaExtender = makeExtendSchemaPlugin(_build => ({
|
||||||
ageAtDeath: Int @requires(columns: ["dateOfBirth", "dateOfDeath"])
|
ageAtDeath: Int @requires(columns: ["dateOfBirth", "dateOfDeath"])
|
||||||
height(units:Units): String @requires(columns: ["height"])
|
height(units:Units): String @requires(columns: ["height"])
|
||||||
weight(units:Units): String @requires(columns: ["weight"])
|
weight(units:Units): String @requires(columns: ["weight"])
|
||||||
|
penisLength(units:Units): String @requires(columns: ["penis_length"])
|
||||||
|
penisGirth(units:Units): String @requires(columns: ["penis_girth"])
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
resolvers: {
|
resolvers: {
|
||||||
|
@ -47,6 +49,20 @@ const schemaExtender = makeExtendSchemaPlugin(_build => ({
|
||||||
? kgToLbs(parent.weight).toString()
|
? kgToLbs(parent.weight).toString()
|
||||||
: 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();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|