From e9277028e2ce0c4bad0340591bd8f87f62ab7805 Mon Sep 17 00:00:00 2001 From: Niels Simenon Date: Sat, 9 Nov 2019 01:22:50 +0100 Subject: [PATCH] Added Mike Adriano scraper (True Anal, All Anal, Swallowed, Nympho). Updated README. --- README.md | 30 +++ assets/components/release/release.vue | 28 ++- assets/img/clock2.svg | 5 + assets/img/stopwatch.svg | 5 + migrations/20190325001339_releases.js | 2 +- public/css/style.css | 7 + seeds/00_networks.js | 6 + seeds/01_sites.js | 122 +++++++++--- seeds/02_tags.js | 39 ++-- src/fetch-releases.js | 2 +- src/releases.js | 1 + src/scrapers/index.js | 2 + src/scrapers/mikeadriano.js | 256 ++++++++++++++++++++++++++ src/scrapers/realitykings.js | 107 ++++++++--- src/scrapers/template.js | 6 +- webpack.config.babel.js | 3 + 16 files changed, 547 insertions(+), 74 deletions(-) create mode 100644 assets/img/clock2.svg create mode 100644 assets/img/stopwatch.svg create mode 100644 src/scrapers/mikeadriano.js diff --git a/README.md b/README.md index 3a2a5c3e..1dd19b52 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,31 @@ Running `npm start` without any arguments will run the web server. * Hot Legs and Feet * House of Taboo * Only Blowjob +* **Dogfart Network** + * Barb Cummings + * Black Meat White Feet + * Blacks On Blondes + * Blacks On Boys + * Blacks On Cougars + * Candy Monroe + * Cuckold Sessions + * Cumbang + * Dogfart Behind The Scenes + * Glory Hole + * Gloryholes And Handjobs + * Gloryholy Initiations + * Interracial Blowbang + * Interracial Pickups + * Katie Thomas + * Ruth Blackwell + * Spring Thomas + * The Minion + * Watching My Daughter Go Black + * Watching My Mom Go Black + * We Fuck Black Girls + * Wife Writing + * Zebra Girls +* **Evil Angel** * **Jules Jordan** * **Kink** * 30 Minutes of Torment @@ -182,6 +207,11 @@ Running `npm start` without any arguments will run the web server. * Whipped Ass * Wired Pussy * **LegalPorno** +* **Mike Adriano** + * All Anal + * True Anal + * Nympho + * Swallowed * **MOFOS** * Blogs * Don't Break Me diff --git a/assets/components/release/release.vue b/assets/components/release/release.vue index 2b2d41e3..b5a001fc 100644 --- a/assets/components/release/release.vue +++ b/assets/components/release/release.vue @@ -78,11 +78,14 @@ {{ release.network.name }}: + >{{ release.network.name }}: + + {{ release.network.name }}: {{ release.site.name }} +

+ + + {{ Math.floor(release.duration / 3600) }}: + {{ Math.floor((release.duration % 3600) / 60).toString().padStart(2, '0') }}: + {{ (release.duration % 60).toString().padStart(2, '0') }} +

+

+ +clock2 + + diff --git a/assets/img/stopwatch.svg b/assets/img/stopwatch.svg new file mode 100644 index 00000000..d779917e --- /dev/null +++ b/assets/img/stopwatch.svg @@ -0,0 +1,5 @@ + + +stopwatch + + diff --git a/migrations/20190325001339_releases.js b/migrations/20190325001339_releases.js index 32fa68b0..3b72e9cb 100644 --- a/migrations/20190325001339_releases.js +++ b/migrations/20190325001339_releases.js @@ -124,7 +124,7 @@ exports.up = knex => Promise.resolve() table.integer('dislikes') .unsigned(); - table.integer('rating') + table.float('rating', 2) .unsigned(); table.boolean('deep'); diff --git a/public/css/style.css b/public/css/style.css index 322f9952..553d9409 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -185,6 +185,7 @@ margin: 0 0 .5rem 0; } .row .icon[data-v-2bc41e74] { + width: 1rem; fill: rgba(0, 0, 0, 0.7); margin: 0 .5rem 0 0; } @@ -203,6 +204,12 @@ display: inline-block; width: .6rem; } +.duration[data-v-2bc41e74] { + font-size: 0; +} +.duration-segment[data-v-2bc41e74] { + font-size: 1rem; +} .date-link[data-v-2bc41e74], .site-link[data-v-2bc41e74], .network-link[data-v-2bc41e74], diff --git a/seeds/00_networks.js b/seeds/00_networks.js index 74a123ed..97d329e6 100644 --- a/seeds/00_networks.js +++ b/seeds/00_networks.js @@ -62,6 +62,12 @@ const networks = [ url: 'https://www.legalporno.com', description: 'The Best HD Porn For You!', }, + { + slug: 'mikeadriano', + name: 'Mike Adriano', + url: null, + description: null, + }, { slug: 'mofos', name: 'MOFOS', diff --git a/seeds/01_sites.js b/seeds/01_sites.js index 7e2166cf..6de9ebd1 100644 --- a/seeds/01_sites.js +++ b/seeds/01_sites.js @@ -1235,6 +1235,34 @@ function getSites(networksMap) { description: 'The Best HD Porn For You!', network_id: networksMap['legalporno'], }, + { + slug: 'trueanal', + name: 'True Anal', + url: 'https://trueanal.com', + description: "TrueAnal is the hottest site with all hardcore Anal content and only the most popular pornstars getting their asses pounded and gapped with huge cock and more!", + network_id: networksMap['mikeadriano'], + }, + { + slug: 'allanal', + name: 'All Anal', + url: 'https://allanal.com', + description: "Popular babes getting their tight asses filled with cock! Pure anal fucking only at AllAnal!", + network_id: networksMap['mikeadriano'], + }, + { + slug: 'nympho', + name: 'Nympho', + url: 'https://nympho.com', + description: "These Babes have an appetite for nasty, sloppy fucking!", + network_id: networksMap['mikeadriano'], + }, + { + slug: 'swallowed', + name: 'Swallowed', + url: 'https://swallowed.com', + description: "Swallowed is a Premium adult website for the hottest Blowjobs content online with only the most popular pornstars swallowing cock!", + network_id: networksMap['mikeadriano'], + }, // MOFOS { slug: 'girlsgonepink', @@ -1815,15 +1843,63 @@ function getSites(networksMap) { name: 'We Live Together', url: 'https://www.welivetogether.com/', description: "We are girls that love to eat pussy and We Live Together! Every week we go out on the streets, bars, parties, malls... wherever and we pick up the cutest lesbians and invite them to come over and party at our apartment. From our girl friends at college, to roommates, and friends of friends.. we're always looking for the hottest lesbian girls around! We Live Together has hundreds of lesbian videos for you to download right from Reality Kings... it's the sexiest lesbian porn anywhere guys and gals! :-) Come watch us eat pussy and work our dildo magic on gorgeous, sexy girls. We love to get together and get off in steamy hot threesome and foursome lesbian movies! We promise you're going to love our amazing collection of lesbian porn. Thanks for dropping in to the We Live Together Apartment, hope you enjoy your visit! Love xoxo Brittney, Taylor, Nicole & All the Girls", - parameters: null, + parameters: JSON.stringify({ siteId: 3 }), slug: 'welivetogether', network_id: networksMap['realitykings'], }, + { + name: 'Black GFs', + url: 'https://www.realitykings.com/scenes?site=47', + description: '', + parameters: null, + slug: 'blackgfs', + network_id: networksMap['realitykings'], + }, + { + name: 'Dare Dorm', + url: 'https://www.daredorm.com/', + description: '', + parameters: JSON.stringify({ siteId: 48 }), + slug: 'daredorm', + network_id: networksMap['realitykings'], + }, + { + name: 'GF Revenge', + url: 'https://www.gfrevenge.com/', + description: '', + parameters: JSON.stringify({ siteId: 49 }), + slug: 'gfrevenge', + network_id: networksMap['realitykings'], + }, + { + name: 'Horny Birds', + url: 'https://www.realitykings.com/scenes?site=50', + description: '', + parameters: null, + slug: 'hornybirds', + network_id: networksMap['realitykings'], + }, + { + name: 'Crazy College GFs', + url: 'https://www.realitykings.com/scenes?site=51', + description: '', + parameters: null, + slug: 'crazycollegegfs', + network_id: networksMap['realitykings'], + }, + { + name: 'Crazy Asian GFs', + url: 'https://www.crazyasiangfs.com/', + description: '', + parameters: JSON.stringify({ siteId: 52 }), + slug: 'crazyasiangfs', + network_id: networksMap['realitykings'], + }, { name: 'Teens Love Huge Cocks', url: 'https://www.teenslovehugecocks.com/', description: "Teens Love Big Cocks is dedicated to providing you the hottest teens getting fucked by the biggest cocks! Every week Reality Kings introduces another teen to a big hot meat rod! When these girls see a big throbbing penis they can't resist shoving it in their hot teen mouths. These girl next door types are no slouches when it comes to oral sex! Watch them deepthroat & gag on a mouth full of cock before taking big hot loads all over their pretty faces. The fun doesn't stop there! These girls love getting their tight teen pussy & asses spread wide and pounded by massive dicks! These girls won't settle for less & there is no dick too large. Start downloading TeensLoveBigCock porn videos & HD quality pictures now and watch teen pussy get fucked like you've never seen before!", - parameters: null, + parameters: JSON.stringify({ siteId: 42 }), slug: 'teenslovehugecocks', network_id: networksMap['realitykings'], }, @@ -1831,7 +1907,7 @@ function getSites(networksMap) { name: 'Big Naturals', url: 'https://www.bignaturals.com/', description: "If you think there is nothing like big natural breasts, Big Naturals welcomes you home. Reality Kings brings you nothing but the hottest amateur big tit women. We're talking about some seriously big boobs. Sexy women with big bouncy tits who love to get it on. These women don't hesitate to let their big natural tits get fucked and let those massive juggs bounce! Big Naturals has hundreds of high quality videos available for download. If into tits, this is the place to be. There's no plastic parts here, only big natural boobs! There's thousands of high resolution pics available to download as well. Check out any of our top rated scenes for the biggest, huge natural tits. Hooters, fun bags, juggs... whatever you want to call them Reality Kings and Big Naturals have the hottest big boobs you'll find anywhere. Sit back, relax, and watch the titties bounce... Reality Kings style!", - parameters: null, + parameters: JSON.stringify({ siteId: 5 }), slug: 'bignaturals', network_id: networksMap['realitykings'], }, @@ -1839,7 +1915,7 @@ function getSites(networksMap) { name: 'Money Talks', url: 'https://www.moneytalks.com/', description: "Money Talks... bullshit walks. We all know the saying, but at Reality Kings we like to prove it! Just watch us approach everyday people on the street and ask them what they will do for some real American Greenbacks! Check out smokin' hot amateurs preform in porn videos or watch crazy college kids preform insane stunts on film... all in exchange for cold hard cash. People will do anything when Money Talks! Watch as we offer cash in exchange for one, AMAZING blow job! From crazy Spring Breakers to the girl next door, we find some amazing sluts and see just what they'll do for the loot--girls that give up the booty, for the booty! Arrr! Reality Kings has every high quality Money Talks episode available for download. We're talking about some seriously hot videos here. You won't find this crazy porn content anywhere else! Remember, Money Talks... bullshit walks!", - parameters: null, + parameters: JSON.stringify({ siteId: 28 }), slug: 'moneytalks', network_id: networksMap['realitykings'], }, @@ -1847,7 +1923,7 @@ function getSites(networksMap) { name: 'Moms Lick Teens', url: 'https://www.momslickteens.com/', description: 'Hot moms know how to fuck, especially when they have a lot of pent up energy. MomsLickTeens.com is where all the magic happens between lustful milf minxes and curious 18+ teen bombshells in HD porn videos. Mature horny women love to sample a fresh batch of pussy and ass whenever possible here at Reality Kings. They love teaching the carnal arts to eager younger women who crave a deeper understanding of the female body. Our bodacious mommies love exploring the anatomy of their fresh-faced lesbian lovers and engage in cunnilingus and anilingus within seconds. Naked women licking, sucking, scissoring, and toying their gaping pussy and assholes with a plethora of adult toys is absolutely riveting to watch. You’ll be aroused by RK girls of different ages rolling around together in sweaty sex scenes. Moms Lick Teens features limber tongues exploring the deepest recesses of female erogenous zones often eliciting projectile squirt orgasms. The phenomenon of female ejaculation occurs regularly in our premium erotica so get a load of it while blowing your own load to our buxom mommies today!', - parameters: null, + parameters: JSON.stringify({ siteId: 43 }), slug: 'momslickteens', network_id: networksMap['realitykings'], }, @@ -1863,7 +1939,7 @@ function getSites(networksMap) { name: 'Milf Hunter', url: 'https://www.milfhunter.com/', description: "Reality Kings presents MILF Hunter the ORIGINAL reality porn site dedicated to MILFs and mature sex content. If you don't know what a MILF is, allow us to explain... we're talking about sex starved, smokin' hot moms that are in need of a little attention--a MILF, a Mother I'd Like to Fuck! We've all seen these moms at the mall, the beach, and around town. Watch every week as the Hunter captures another hottie on film and gives them what they've been craving... some dick! These moms are seriously hot MILFs and they appear in the most incredible high quality pics and movies! We have hundreds of mature porn videos available for you to download. Or if you're looking for photos we have thousands of high resolution MILF porn pics directly from the MILF Hunter! Reality Kings brings you the best mature sex scenes around so why not join the MILF Hunter hunt down mature moms across America...", - parameters: null, + parameters: JSON.stringify({ siteId: 2 }), slug: 'milfhunter', network_id: networksMap['realitykings'], }, @@ -1871,7 +1947,7 @@ function getSites(networksMap) { name: 'Pure 18', url: 'https://www.realitykings.com/scenes?site=31', description: `There's a lot of stuff out there that claims to be "pure", from spring water to gold chains, who knows what's actually legit$2 Reality Kings presents Pure 18, legit, 100% verified 18 year old sex scenes--no bullshit, only incredible 18 year old girls! These hot girls are the real deal, barely legal, smokin' hot babes looking for some fun. Don't let their age fool you, these chicks know how to work a cock. Tight pussies and tight asses, the finest sex scenes around, that's what Pure 18 is all about! If you love watching amazing blow jobs, you're going to love this content. Download hundreds of high quality videos and pics featuring 100% verified 18 year old sex! These cuties are not shy about sex. Watch them take on monster cocks and love every minute of it. Pure 18, legit, verified, real 18 year old girls hungry for a cock meat sandwich!`, - parameters: '{"altLayout":true}', + parameters: null, slug: 'pure18', network_id: networksMap['realitykings'], }, @@ -1887,7 +1963,7 @@ function getSites(networksMap) { name: 'Cum Fiesta', url: 'https://www.cumfiesta.com/', description: `"Is this the fiesta $4 " Of course, welcome to the Cum Fiesta! Every week Reality Kings welcomes another hottie to the party... the dick sucking party! :-) When the girl (or girls!) arrive they show us the super secret password (watch a trailer to find out) and the party begins! As their clothes come off, these babes begin to show off their amazing oral skills. Amateur chicks taking the biggest facial cumshots, that's what Cum Fiesta is about! There are no pansy blow jobs here, these chicks give the best head around, and take huge cum shots to their face at the same time. Download hundreds of high quality videos and pics of semen swallowing hotties. Join the party that features amateurs, newbies, and even the girl next door! These babes love to suck cock and take incredible cum shots you'll find no where else! This is no siesta folks, it's a Cum Fiesta!`, - parameters: null, + parameters: JSON.stringify({ siteId: 10 }), slug: 'cumfiesta', network_id: networksMap['realitykings'], }, @@ -1895,7 +1971,7 @@ function getSites(networksMap) { name: '8th Street Latinas', url: 'https://www.8thstreetlatinas.com/', description: "Scientists say that the sun is what makes the temperature rise south of the equator, but we think its the women! If you haven't seen the chicas (women) from 8th Street Latinas, you're in for a spicy treat. From the famous Calle 8 (8th Street) in Miami, Reality Kings brings you the some incredibly hot latinas! We're talking Cubans, Dominicans, Panamanians, and other sexy latinas from South and Central America. These babes aim to please with their tanned bodies and deliciously round asses. Damn, we can't get enough! 8th Street Latinas has some caliente (hot) content for you to download, featuring the hottest latina sex scenes around. These are not tanned white chicks, these are REAL, hot latinas who know how to get your blood pumping. If you think you can handle the heat, grab your pair of shorts and flip-flops and let's head to Miami... 8th Street Latinas has some incredible latina porn for you!", - parameters: null, + parameters: JSON.stringify({ siteId: 1 }), slug: '8thstreetlatinas', network_id: networksMap['realitykings'], }, @@ -1903,7 +1979,7 @@ function getSites(networksMap) { name: "Mike's Apartment", url: 'http://www.mikesapartment.com/', description: `There's a room for rent in Mikes Apartment and Mike has found another hot chick to fill the vacancy! Join Mike on his search for roommates to help pay the bills. If these hot euro babes don't have the money, that's alright, Mike offers them the room in exchange for a few hours of masturbation and fun! And if the girl is traveling with a companion, thats not a problem... Mike just creates another steamy euro sex film for his "private" collection. Seriously, these babes are Europe's finest and Mike is your connoisseur of European booty! From their tight bodies, to their thick accents, these ladies know how to please and excite. Reality Kings offers hundreds of our incredible european porn movies and pics for you to download, and you don't have to travel to Moscow to get them. If you're looking for original, hot, European porn content, welcome to your new home: Mikes Apartment.`, - parameters: '{"altLayout":true}', + parameters: JSON.stringify({ siteId: 25 }), slug: 'mikesapartment', network_id: networksMap['realitykings'], }, @@ -1911,7 +1987,7 @@ function getSites(networksMap) { name: 'In the VIP', url: 'http://www.inthevip.com/', description: "Ever wonder what happens In The VIP$3 Reality Kings takes you to the hottest night clubs in the country to show you exactly what goes on in the VIP room. When the club is packed, the music is pumpin', and the ladies are looking this HOT, you know it's going to be a damn good time! Grab a drink and step into the VIP room. Check out these gorgeous babes shaking their asses and flashing the camera. You will never see ladies like this in some whack ass bar, only in the most exclusive VIP rooms. As the party gets going, the clothes come off, and the panties drop! Watch some amazing free VIP porn movies, featuring these hotties having sex VIP style. We're talking about some down and dirty club sex featuring smokin' hot sluts. These chicks came for a good time and they've found it! Join the exclusive party In The VIP.", - parameters: '{"altLayout":true}', + parameters: JSON.stringify({ siteId: 22 }), slug: 'inthevip', network_id: networksMap['realitykings'], }, @@ -1919,7 +1995,7 @@ function getSites(networksMap) { name: 'CFNM Secret', url: 'https://www.realitykings.com/scenes?site=9', description: "Shhh, keep your voice down! At Reality Kings we have a secret to share, the CFNM Secret! What's this secret all about$5 Clothed Females and Nude Males (CFNM)! Beautiful women dressed to impress and an unsuspecting male who is about to discover the secret for himself! These voyeurs are interested in every inch of the male body, touching and grabbing, they won't stop until they've had enough. Who wouldn't mind being these ladies play things$6 Gorgeous babes teasing and embarrassing men for their own fun and pleasure. Vulnerable guys being inspected and scrutinized in amazing high quality voyeur sex scenes. From CFNM handjobs to CFNM party scenes Reality Kings offers the hottest women enjoying the male body like never before. Browse our free CFNM videos below to download high quality pics and trailers. You're going to tell your friends about this secret, the CFNM Secret!", - parameters: '{"altLayout":true}', + parameters: null, slug: 'cfnmsecret', network_id: networksMap['realitykings'], }, @@ -1959,7 +2035,7 @@ function getSites(networksMap) { name: 'Captain Stabbin', url: 'https://www.captainstabbin.com/', description: "Hop aboard the S.S. Stabbin and join Captain Stabbin on his trip to analize the seven seas! What's better than a girl with a hot pussy$8 A girl with a hot pussy getting poked in the ass! Reality Kings invites you to the worlds greatest anal sex adventure. These babes don't need a boarding pass to climb aboard this ship, only a hot body and a gorgeous ass. Watch as the Captain sets course for the anal islands in search of the best anal sex scenes around! Download hundreds of incredible anal sex movies and pics in stunning high quality formats. Captain Stabbin brings you the very best booty content, from her first anal sex scene, to amazing boat sex scenes at sea, every episode is sure to please! These girls are ready for a stern spanking (pun intended)! Raise the main sail, set course, and join Captain Stabbin on his anal adventure! Arrr!", - parameters: '{"altLayout":true}', + parameters: JSON.stringify({ siteId: 8 }), slug: 'captainstabbin', network_id: networksMap['realitykings'], }, @@ -1967,7 +2043,7 @@ function getSites(networksMap) { name: 'Big Tits Boss', url: 'https://www.realitykings.com/scenes?site=6', description: "Reality Kings presents Big Tits Boss! Have you been checking out that smokin' hot female executive around the office$10 Damn she's fine! She wears those short skirts and tight tops that make her huge tits pop out! Time to stop slackin' off fellas, because these ladies have been watching you closely. We're talking about the sexy women with the big tits at work. CEOs, Lawyers, CIOs, CFOs, these babes don't take any bullshit and they'll gladly use you like a toy whenever they please! Big Tits Boss has amazing high quality videos and pics available for download, featuring some very powerful women with awesome big natural tits. You won't mind being called into the office for a little discipline this time around! It's all business when these hotties are in the office... so fill out your TPS reports and be on your best behavior if you're looking for the promotion from the Big Tits Boss!", - parameters: '{"altLayout":true}', + parameters: null, slug: 'bigtitsboss', network_id: networksMap['realitykings'], }, @@ -1975,7 +2051,7 @@ function getSites(networksMap) { name: 'Euro Sex Parties', url: 'https://www.realitykings.com/scenes?site=13', description: "Pack your bags folks, we're headed to Europe! It's time to join two best friends as they travel across Europe and throw some amazing Euro Sex Parties. Forget about boring 1on1 sex scenes. Get ready for hardcore threesomes, foursomes, and fivesomes! Hot European porn directly from the source, just the way we like it. Euro babes with tight bodies taking on multiple cocks... what could be better$9 How about watching them eat pussy as well! Now that's a group sex party we'd love to attend. From hardcore group sex to hardcore gangbangs, this is the hottest content anywhere. Euro Sex Parties offers hundreds of European porn videos and pics to download in stunning high quality formats. Don't pack your bags yet, Reality Kings has tons of free movies and pics for you to download right here! Join us on our European vacation, and we'll throw a few Euro Sex Parties along the way.", - parameters: '{"altLayout":true}', + parameters: null, slug: 'eurosexparties', network_id: networksMap['realitykings'], }, @@ -2007,7 +2083,7 @@ function getSites(networksMap) { name: 'Happy Tugs', url: 'https://www.happytugs.com/', description: "Come on dudes, who doesn't like a happy ending$13 We've all seen those hole in the wall Asian massage parlors! Finally there is a site that celebrates the hand job. Asian beauties rubbing massage oil all over, what could be better$14 These babes know how to work out the kinks, seriously amazing rub 'n tug jobs. Happy Tugs captures hidden camera footage from inside one of the country's best sexual massage parlors. The dudes come in looking for a little rub down and, for a few dollars more, get a full servicing. It doesn't get any better than this, hand jobs and hot Asian babes. Check out our amazing happy ending videos, with babes rubbing their oil soaked breasts all over their favorite customers. Strip down, jump on the massage table and get your wallet out, Happy Tugs will ensure you get a very happy ending!", - parameters: null, + parameters: JSON.stringify({ siteId: 19 }), slug: 'happytugs', network_id: networksMap['realitykings'], }, @@ -2015,7 +2091,7 @@ function getSites(networksMap) { name: 'HD Love', url: 'https://www.realitykings.com/scenes?site=20', description: 'Looking for incredibly hot porn videos in HD$12 Reality Kings showcases it all in hardcore erotica here at HDLove.com. Our premium adult content will satisfy your deepest carnal desires in stunning high-definition sex scenes. Feast your eyes on bodacious naked babes who love nothing more than to fuck on camera for you. Our hi-def movies capture every inch of their voluptuous bodies in vivid detail. Perfect round boobs and perky nipples are just the start. These jezebels proudly display their killer asses and dripping wet pussies before ravaging huge cocks like their lives depended on it. Whether you’re in the mood for horny 18+ teen nymphos or seasoned mature women the raunchiest scenes will keep you cumming back to HD Love. Our eager to please divas love to disrobe and spread as much love around as they can offering up deepthroat gagging blowjobs to anyone daring enough. They yearn for deep anal penetrations and are always up for a sweaty orgy so witness it all in crystal clear resolution. Catch every microscopic detail and blow your load repeatedly with the best that RK has in store!', - parameters: '{"altLayout":true}', + parameters: null, slug: 'hdlove', network_id: networksMap['realitykings'], }, @@ -2079,15 +2155,15 @@ function getSites(networksMap) { name: 'Moms Bang Teens', url: 'https://www.momsbangteens.com/', description: "Reality Kings presents the first website dedicated to hot moms who love to bang 18+ teens. Moms Bang Teens features the sexiest MILFs on the web, and these MILFs are all about fucking young guys on camera. If you remember lusting after one of your friend's hot moms back in grade school, then you know exactly what Moms Bang Teens is all about. Imagine if instead of just fantasizing about that sexy mother, you actually got to bang her. These are the same hot moms you see at your local supermarket and shopping at your neighborhood mall. Some of them are married and never get the attention they need. While others are just horny and sexy moms who never got tied down with a husband. Instead they like to go out and find hot young studs that know how to fuck them right. These are experienced and mature women who know what they want; young 18+ teens that can give them that rock hard cock.", - parameters: null, + parameters: JSON.stringify({ siteId: 27 }), slug: 'momsbangteens', network_id: networksMap['realitykings'], }, { name: 'Sneaky Sex', url: 'https://www.sneakysex.com/', - description: null, - parameters: null, + description: "Sneaky dirty sex! They are fucking and nobody can see, otherwise they will have a HUGE problem. When no one is watching, these horny MILFs and Teens are having sneaky sex!", + parameters: JSON.stringify({ siteId: 46 }), slug: 'sneakysex', network_id: networksMap['realitykings'], }, @@ -2111,7 +2187,7 @@ function getSites(networksMap) { name: 'Mike in Brazil', url: 'https://www.realitykings.com/scenes?site=24', description: "Are you ready for the never ending booty vacation$24 Join Mike In Brazil as he explores the wild, the exotic, and the gorgeous women of South America! If you have never been to Brazil, don't worry... Mike will give you a crash course on the most amazing ASSet of their native women. We're talking about deliciously tanned, round, thong clad Brazilian ass! These booties will not disappoint. Mike exports nothing but the finest, Grade A, Brazilian porn directly to your computer screen. Check out the hottest Brazilian ass around, wearing nothing but bikinis and thongs that are sure to get your blood pumping! These hotties spend hours working on their amazing tans to show off their bodies... look at those incredible tan lines! Mike In Brazil features some amazing hardcore sex, from anal to Brazilian facials, we're sure you're going to be planning a trip to Brazil soon. What are you waiting for$25 Join the never ending booty vacation with Mike In Brazil!", - parameters: '{"altLayout":true}', + parameters: null, slug: 'mikeinbrazil', network_id: networksMap['realitykings'], }, @@ -2159,7 +2235,7 @@ function getSites(networksMap) { name: 'Round and Brown', url: 'https://www.roundandbrown.com/', description: `Chocolate lovers out there, Reality Kings presents to you... Round And Brown, the porn site that caters to horny dudes who have a mighty craving for fine "sistah" booties. The ladies featured in these ebony porn movies are SIZZLING HOT, like a newly melted chocolate fondue! We're talking about some damn fine black booties! If it's Round And Brown, it gets the special lube treatment, no exceptions! Think you can handle this collection of premium ebony ass$1 There's no skinny white girls here, only gorgeous black beauties with deliciously round booties, featured in the best hardcore ebony sex videos around! Reality Kings is the only one who can bring you this amazing collection of black girl porn. If you love big round asses, gorgeous black babes, and amazing tits we have the videos and pics you're looking for. Warning: This chocolate may melt in your hand and your mouth... but who cares, if it's Round And Brown!`, - parameters: null, + parameters: JSON.stringify({ siteId: 33 }), slug: 'roundandbrown', network_id: networksMap['realitykings'], }, @@ -2167,7 +2243,7 @@ function getSites(networksMap) { name: 'Monster Curves', url: 'https://www.realitykings.com/scenes?site=29', description: "Forget about those toothpick size runway models, give us some ladies with curves-- Monster Curves! If you love your women round and juicy, ladies with some meat on their bones... then we have the content for you! We're talking about women with hips that don't quit. Incredibly round asses that will make your mouth water! Big booty girls with big round asses. Only people as obsessed as us could bring you this many pairs of perfects hips and asses! Download hundreds of movies and pics featuring gorgeous girls with amazing curves (we call them Monster Curves). Check out some of our free trailers below, these girls and their round butts and perfect hips are sure to wet your appetite! Every week, Reality Kings brings you nothing but the finest butts, the sexy round asses that jiggle when you grab 'em, the women with the Monster Curves!", - parameters: '{"altLayout":true}', + parameters: null, slug: 'monstercurves', network_id: networksMap['realitykings'], }, diff --git a/seeds/02_tags.js b/seeds/02_tags.js index eae9d3fa..6c02f0ed 100644 --- a/seeds/02_tags.js +++ b/seeds/02_tags.js @@ -115,11 +115,6 @@ function getTags(groupsMap) { alias_for: null, group_id: groupsMap['ethnicity'], }, - { - name: 'ass licking', - slug: 'ass-licking', - alias_for: null, - }, { name: 'athletic', slug: 'athletic', @@ -131,6 +126,11 @@ function getTags(groupsMap) { slug: 'ass-to-mouth', alias_for: null, }, + { + name: 'ass eating', + slug: 'ass-eating', + alias_for: null, + }, { name: 'ball licking', slug: 'ball-licking', @@ -395,8 +395,8 @@ function getTags(groupsMap) { group_id: groupsMap['group'], }, { - name: 'gaping', - slug: 'gaping', + name: 'gapes', + slug: 'gapes', alias_for: null, }, { @@ -647,6 +647,11 @@ function getTags(groupsMap) { slug: 'slapping', alias_for: null, }, + { + name: 'sloppy blowjob', + slug: 'sloppy-blowjob', + alias_for: null, + }, { name: 'socks', slug: 'socks', @@ -812,16 +817,20 @@ function getTagAliases(tagsMap) { }, { name: 'anal gape', - alias_for: tagsMap['gaping'], + alias_for: tagsMap['gapes'], }, { name: 'anilingus', - alias_for: tagsMap['ass-licking'], + alias_for: tagsMap['ass-eating'], }, { name: 'asians', alias_for: tagsMap['asian'], }, + { + name: 'ass licking', + alias_for: tagsMap['ass-eating'], + }, { name: 'ass fucking', alias_for: tagsMap['anal'], @@ -1144,15 +1153,15 @@ function getTagAliases(tagsMap) { }, { name: 'gape', - alias_for: tagsMap['gaping'], + alias_for: tagsMap['gapes'], }, { - name: 'gapes', - alias_for: tagsMap['gaping'], + name: 'gaping', + alias_for: tagsMap['gapes'], }, { name: 'gapes (gaping asshole)', - alias_for: tagsMap['gaping'], + alias_for: tagsMap['gapes'], }, { name: 'group sex', @@ -1248,11 +1257,11 @@ function getTagAliases(tagsMap) { }, { name: 'rimming', - alias_for: tagsMap['ass-licking'], + alias_for: tagsMap['ass-eating'], }, { name: 'rimjob', - alias_for: tagsMap['ass-licking'], + alias_for: tagsMap['ass-eating'], }, { name: 'role play', diff --git a/src/fetch-releases.js b/src/fetch-releases.js index 6a71044a..c68a6ff2 100644 --- a/src/fetch-releases.js +++ b/src/fetch-releases.js @@ -277,7 +277,7 @@ async function fetchNewReleases(scraper, site, afterDate, accReleases = [], page const oldestReleaseOnPage = latestReleases.slice(-1)[0].date; - if (uniqueReleases.length > 0 && moment(oldestReleaseOnPage).isAfter(afterDate) && (!oldestReleaseOnPage && page < argv.pages)) { + if (uniqueReleases.length > 0 && moment(oldestReleaseOnPage).isAfter(afterDate) && (oldestReleaseOnPage || page < argv.pages)) { return fetchNewReleases(scraper, site, afterDate, accReleases.concat(uniqueReleases), page + 1); } diff --git a/src/releases.js b/src/releases.js index 7f80f4ee..877f8e8b 100644 --- a/src/releases.js +++ b/src/releases.js @@ -29,6 +29,7 @@ async function curateRelease(release) { actors, director: release.director, tags, + duration: release.duration, photos: media.filter(item => item.role === 'photo'), poster: media.filter(item => item.role === 'poster')[0], trailer: media.filter(item => item.role === 'trailer')[0], diff --git a/src/scrapers/index.js b/src/scrapers/index.js index f0400a1d..bd58697e 100644 --- a/src/scrapers/index.js +++ b/src/scrapers/index.js @@ -10,6 +10,7 @@ const evilangel = require('./evilangel'); const julesjordan = require('./julesjordan'); const kink = require('./kink'); const legalporno = require('./legalporno'); +const mikeadriano = require('./mikeadriano'); const mofos = require('./mofos'); const pervcity = require('./pervcity'); const privateNetwork = require('./private'); // reserved keyword @@ -30,6 +31,7 @@ module.exports = { julesjordan, kink, legalporno, + mikeadriano, mofos, pervcity, private: privateNetwork, diff --git a/src/scrapers/mikeadriano.js b/src/scrapers/mikeadriano.js new file mode 100644 index 00000000..24285c5b --- /dev/null +++ b/src/scrapers/mikeadriano.js @@ -0,0 +1,256 @@ +'use strict'; + +/* eslint-disable newline-per-chained-call */ +const bhttp = require('bhttp'); +const { JSDOM } = require('jsdom'); +const cheerio = require('cheerio'); +const moment = require('moment'); + +const { matchTags } = require('../tags'); + +const defaultTags = { + swallowed: ['blowjob', 'deepthroat', 'facefuck'], + trueanal: ['anal'], + allanal: ['anal', 'fmf'], + nympho: [], +}; + +const descriptionTags = { + 'anal cream pie': 'anal creampie', + 'ass to mouth': 'ass to mouth', + 'cream pie in her ass': 'anal creampie', + 'eats ass': 'ass eating', + facial: 'facial', + gaped: 'gaping', + gapes: 'gaping', + gape: 'gaping', + 'rectal cream pie': 'anal creampie', + rimming: 'ass eating', +}; + +function deriveTagsFromDescription(description) { + const matches = (description || '').toLowerCase().match(new RegExp(Object.keys(descriptionTags).join('|'), 'g')); + + return matches + ? matches.map(match => descriptionTags[match]) + : []; +} + +async function scrapeLatestA(html, site) { + const { document } = new JSDOM(html).window; + const sceneElements = document.querySelectorAll('.content-item-large, .content-item'); + + return Promise.all(Array.from(sceneElements, async (element) => { + const $ = cheerio.load(element.innerHTML, { normalizeWhitespace: true }); + + const titleElement = element.querySelector('h3.title a'); + const title = titleElement.textContent; + const url = titleElement.href; + const entryId = url.split('/').slice(-2)[0]; + + const descriptionElement = element.querySelector('.desc'); + const description = descriptionElement && descriptionElement.textContent.trim(); + const date = moment(element.querySelector('.date, time').textContent, 'Do MMM YYYY').toDate(); + + const actors = Array.from(element.querySelectorAll('h4.models a'), actorElement => actorElement.textContent); + + const durationString = element.querySelector('.total-time').textContent.trim(); + // timestamp is somethines 00:00, sometimes 0:00:00 + const duration = durationString.split(':').length === 3 + ? moment.duration(durationString).asSeconds() + : moment.duration(`00:${durationString}`).asSeconds(); + + const ratingElement = element.querySelector('.rating'); + const stars = ratingElement && ratingElement.dataset.rating; + + const [poster, ...primaryPhotos] = Array.from(element.querySelectorAll('img'), imageElement => imageElement.src); + const secondaryPhotos = $('.thumb-top, .thumb-bottom') + .map((photoIndex, photoElement) => $(photoElement).css()['background-image']) + .toArray() + .map(photoUrl => photoUrl.slice(photoUrl.indexOf('http'), photoUrl.indexOf('.jpg') + 4)); + + const photos = [...primaryPhotos, ...secondaryPhotos]; + const tags = await matchTags([...defaultTags[site.slug], ...deriveTagsFromDescription(description)]); + + const scene = { + url, + entryId, + title, + description, + actors, + director: 'Mike Adriano', + date, + duration, + tags, + poster, + photos, + rating: { + stars, + }, + site, + }; + + return scene; + })); +} + +async function scrapeLatestB(html, site) { + const { document } = new JSDOM(html).window; + const sceneElements = document.querySelectorAll('.content-border'); + + return Promise.all(Array.from(sceneElements, async (element) => { + const $ = cheerio.load(element.innerHTML, { normalizeWhitespace: true }); + + const titleElement = element.querySelector('.content-title-wrap a'); + const title = titleElement.title || titleElement.textContent.trim(); + const url = titleElement.href; + const entryId = url.split('/').slice(-2)[0]; + + const description = element.querySelector('.content-description').textContent.trim(); + const date = (moment(element.querySelector('.mobile-date').textContent, 'MM/DD/YYYY') + || moment(element.querySelector('.date').textContent, 'Do MMM YYYY')).toDate(); + const actors = Array.from(element.querySelectorAll('.content-models a'), actorElement => actorElement.textContent); + + const durationString = element.querySelector('.total-time').textContent.trim(); + // timestamp is somethines 00:00, sometimes 0:00:00 + const duration = durationString.split(':').length === 3 + ? moment.duration(durationString).asSeconds() + : moment.duration(`00:${durationString}`).asSeconds(); + + const [poster, ...primaryPhotos] = Array.from(element.querySelectorAll('a img'), imageElement => imageElement.src); + const secondaryPhotos = $('.thumb-mouseover') + .map((photoIndex, photoElement) => $(photoElement).css()['background-image']) + .toArray() + .map(photoUrl => photoUrl.slice(photoUrl.indexOf('http'), photoUrl.indexOf('.jpg') + 4)); + + const photos = [...primaryPhotos, ...secondaryPhotos]; + const tags = await matchTags([...defaultTags[site.slug], ...deriveTagsFromDescription(description)]); + + return { + url, + entryId, + title, + description, + actors, + director: 'Mike Adriano', + date, + duration, + tags, + poster, + photos, + site, + }; + })); +} + +async function scrapeSceneA(html, url, site) { + const { document } = new JSDOM(html).window; + const element = document.querySelector('.content-page-info'); + + const entryId = url.split('/').slice(-2)[0]; + const title = element.querySelector('.title').textContent.trim(); + const description = element.querySelector('.desc').textContent.trim(); + const date = moment(element.querySelector('.post-date').textContent.trim(), 'Do MMM YYYY').toDate(); + + const actors = Array.from(element.querySelectorAll('.models a'), actorElement => actorElement.textContent); + + const durationString = element.querySelector('.total-time').textContent.trim(); + // timestamp is somethines 00:00, sometimes 0:00:00 + const duration = durationString.split(':').length === 3 + ? moment.duration(durationString).asSeconds() + : moment.duration(`00:${durationString}`).asSeconds(); + + const { poster } = document.querySelector('.content-page-header video'); + const { src, type } = document.querySelector('.content-page-header source'); + + const tags = await matchTags([...defaultTags[site.slug], ...deriveTagsFromDescription(description)]); + + return { + url, + entryId, + title, + description, + actors, + director: 'Mike Adriano', + date, + duration, + tags, + poster, + trailer: { + src, + type, + }, + site, + }; +} + +async function scrapeSceneB(html, url, site) { + const { document } = new JSDOM(html).window; + const element = document.querySelector('.content-page-info'); + + const entryId = url.split('/').slice(-2)[0]; + const title = element.querySelector('.title').textContent.trim(); + const description = element.querySelector('.desc').textContent.trim(); + const date = moment(element.querySelector('.date').textContent.trim(), 'Do MMM YYYY').toDate(); + + const actors = Array.from(element.querySelectorAll('.models a'), actorElement => actorElement.textContent); + + const durationString = element.querySelector('.total-time').textContent.trim(); + // timestamp is somethines 00:00, sometimes 0:00:00 + const duration = durationString.split(':').length === 3 + ? moment.duration(durationString).asSeconds() + : moment.duration(`00:${durationString}`).asSeconds(); + + const { poster } = document.querySelector('.content-page-header-inner video'); + const { src, type } = document.querySelector('.content-page-header-inner source'); + + const tags = await matchTags([...defaultTags[site.slug], ...deriveTagsFromDescription(description)]); + + const scene = { + url, + entryId, + title, + description, + actors, + director: 'Mike Adriano', + date, + duration, + tags, + poster, + trailer: { + src, + type, + }, + site, + }; + + return scene; +} + +async function fetchLatest(site, page = 1) { + const { host } = new URL(site.url); + + const res = await bhttp.get(`https://tour.${host}/videos?page=${page}`); + + if (host === 'trueanal.com' || host === 'swallowed.com') { + return scrapeLatestA(res.body.toString(), site); + } + + return scrapeLatestB(res.body.toString(), site); +} + +async function fetchScene(url, site) { + const { host } = new URL(site.url); + const res = await bhttp.get(url); + + if (host === 'trueanal.com' || host === 'swallowed.com') { + return scrapeSceneA(res.body.toString(), url, site); + } + + return scrapeSceneB(res.body.toString(), url, site); +} + +module.exports = { + fetchLatest, + fetchScene, +}; diff --git a/src/scrapers/realitykings.js b/src/scrapers/realitykings.js index faa84257..11b1acad 100644 --- a/src/scrapers/realitykings.js +++ b/src/scrapers/realitykings.js @@ -4,38 +4,71 @@ const Promise = require('bluebird'); const bhttp = require('bhttp'); const { CookieJar } = Promise.promisifyAll(require('tough-cookie')); -const cheerio = require('cheerio'); -const moment = require('moment'); +const { JSDOM } = require('jsdom'); const { matchTags } = require('../tags'); -function scrapeLatest(html, site) { - const $ = cheerio.load(html, { normalizeWhitespace: true }); - const sceneElements = $('.card.card--release').toArray(); +async function scrapeLatest(html, site) { + const { document } = new JSDOM(html).window; - console.log(sceneElements); + const scriptString = document.querySelector('script').textContent; + const prefix = 'window.__JUAN.initialState = {'; - return sceneElements.map((element) => { - const sceneLinkElement = $(element).find('.card-info__title a'); - const title = sceneLinkElement.attr('title'); - const url = `${site.url}${sceneLinkElement.attr('href')}`; - const entryId = url.split('/').slice(-3)[0]; + const dataStart = scriptString.slice(scriptString.indexOf(prefix) + prefix.length - 1); + const dataString = dataStart.slice(0, dataStart.indexOf('};') + 1); + const data = JSON.parse(dataString); - const date = moment.utc($(element).find('.card-info__meta-date').text(), 'MMMM DD, YYYY').toDate(); - const actors = $(element).find('.card-info__cast a').map((actorIndex, actorElement) => $(actorElement).text().trim()).toArray(); + const actorsMap = data.entities.actors; + const tagsMap = data.entities.tags; + const scenes = Object.values(data.entities.releases); - console.log(date, actors, title); + return Promise.all(scenes.map(async (scene) => { + const { + id: entryId, + title, + description, + } = scene; + + const url = `https://www.realitykings.com/scene/${entryId}`; + const date = new Date(scene.dateReleased); + const actors = scene.actors.map(actorId => actorsMap[actorId].name); + + const rawTags = scene.tags.map(tagId => tagsMap[tagId].name); + const tags = await matchTags(rawTags); + + if (!scene.images.poster) { + console.log(site.name, site.id); + console.log(scene); + console.log(title, url, scene.images); + } + + const [poster, ...photos] = scene.images.poster.map(image => image.xl.url); + + const duration = scene.videos.mediabook.length; + const trailer720p = scene.videos.mediabook.files['720p'] && scene.videos.mediabook.files['720p'].urls.view; + const trailer360p = scene.videos.mediabook.files['360p'] && scene.videos.mediabook.files['360p'].urls.view; + + const { likes, dislikes } = scene.stats; return { url, entryId, title, + description, actors, date, - rating: null, + tags, + duration, + poster, + photos, + trailer: { + src: trailer720p || trailer360p, + quality: trailer720p ? 720 : 360, + }, + rating: { likes, dislikes }, site, }; - }); + })); } async function scrapeScene(data, url, site) { @@ -46,23 +79,19 @@ async function scrapeScene(data, url, site) { } = data; const date = new Date(data.dateReleased); - const actors = data.actors - .sort(({ gender: genderA }, { gender: genderB }) => { - if (genderA === 'female' && genderB === 'male') return -1; - if (genderA === 'male' && genderB === 'female') return 1; - - return 0; - }) - .map(actor => actor.name); + const actors = data.actors.map(actor => actor.name); const { likes, dislikes } = data.stats; - const duration = data.videos.mediabook.length; - - console.log(data); const rawTags = data.tags.map(tag => tag.name); const tags = await matchTags(rawTags); + const [poster, ...photos] = data.images.poster.map(image => image.xl.url); + + const duration = data.videos.mediabook.length; + const trailer720p = data.videos.mediabook.files['720p'] && data.videos.mediabook.files['720p'].urls.view; + const trailer360p = data.videos.mediabook.files['360p'] && data.videos.mediabook.files['360p'].urls.view; + return { url, entryId, @@ -72,6 +101,12 @@ async function scrapeScene(data, url, site) { date, duration, tags, + poster, + photos, + trailer: { + src: trailer720p || trailer360p, + quality: trailer720p ? 720 : 360, + }, rating: { likes, dislikes, @@ -81,13 +116,25 @@ async function scrapeScene(data, url, site) { } async function fetchLatest(site, page = 1) { - const res = await bhttp.get(`https://www.realitykings.com/tour/videos/${site.name.replace(/\s+/g, '-').toLowerCase()}/all-categories/all-time/recent/${page}`); + const { hostname, search } = new URL(site.url); - return scrapeLatest(res.body.toString(), site); + if (hostname.match(/(www\.)?realitykings\.com/) && search.match(/\?site=\d+/)) { + const res = await bhttp.get(`${site.url}&page=${page}`); + + return scrapeLatest(res.body.toString(), site); + } + + if (site.parameters && site.parameters.siteId) { + const res = await bhttp.get(`https://www.realitykings.com/scenes?site=${site.parameters.siteId}&page=${page}`); + + return scrapeLatest(res.body.toString(), site); + } + + throw new Error(`Reality Kings site '${site.name}' (${site.url}) not supported`); } async function fetchScene(url, site) { - if (site.isFallback || (site.parameters && site.parameters.altLayout)) { + if (site.isFallback) { throw new Error('Cannot fetch scene details from this resource'); } diff --git a/src/scrapers/template.js b/src/scrapers/template.js index 0907ded7..8a25df99 100644 --- a/src/scrapers/template.js +++ b/src/scrapers/template.js @@ -2,13 +2,13 @@ /* eslint-disable newline-per-chained-call */ const bhttp = require('bhttp'); -const cheerio = require('cheerio'); +const { JSDOM } = require('jsdom'); const moment = require('moment'); const { matchTags } = require('../tags'); function scrapeLatest(html, site) { - const $ = cheerio.load(html, { normalizeWhitespace: true }); + const { document } = new JSDOM(html).window; const sceneElements = $('.scenes-latest').toArray(); return sceneElements.map((element) => { @@ -31,7 +31,7 @@ function scrapeLatest(html, site) { } function scrapeUpcoming(html, site) { - const $ = cheerio.load(html, { normalizeWhitespace: true }); + const { document } = new JSDOM(html).window; const sceneElements = $('.scenes-upcoming').toArray(); return sceneElements.map((element) => { diff --git a/webpack.config.babel.js b/webpack.config.babel.js index 6c16e4eb..11d4ac0f 100644 --- a/webpack.config.babel.js +++ b/webpack.config.babel.js @@ -17,6 +17,9 @@ export default { path.resolve(__dirname, 'assets'), ], loader: 'vue-loader', + options: { + preserveWhitespace: false, + }, }, { test: /\.js$/,