From 49a0dadb34e731d675c23c4d9e2031817755d784 Mon Sep 17 00:00:00 2001 From: Logan Rockmore Date: Wed, 11 Dec 2019 20:49:54 -0700 Subject: [PATCH] feat: Rewrite the Dribbble route. (#3577) --- lib/routes/dribbble/keyword.js | 5 +- lib/routes/dribbble/popular.js | 5 +- lib/routes/dribbble/user.js | 5 +- lib/routes/dribbble/utils.js | 123 +++++++++++++++++++++------------ 4 files changed, 91 insertions(+), 47 deletions(-) diff --git a/lib/routes/dribbble/keyword.js b/lib/routes/dribbble/keyword.js index cb7e6a12bc..c662275cae 100644 --- a/lib/routes/dribbble/keyword.js +++ b/lib/routes/dribbble/keyword.js @@ -2,6 +2,9 @@ const utils = require('./utils'); module.exports = async (ctx) => { const keyword = ctx.params.keyword; + const url = `https://dribbble.com/search/shots/recent?q=${keyword}`; - ctx.state.data = await utils.getData(`Keyword ${keyword}`, `https://dribbble.com/search?q=${keyword}&s=latest`); + const title = `Dribbble - keyword ${keyword}`; + + ctx.state.data = await utils.getData(ctx, url, title); }; diff --git a/lib/routes/dribbble/popular.js b/lib/routes/dribbble/popular.js index d4cbe30a0d..928f8d8361 100644 --- a/lib/routes/dribbble/popular.js +++ b/lib/routes/dribbble/popular.js @@ -2,6 +2,9 @@ const utils = require('./utils'); module.exports = async (ctx) => { const timeframe = ctx.params.timeframe; + const url = `https://dribbble.com/shots/popular${timeframe ? `?timeframe=${timeframe}` : ''}`; - ctx.state.data = await utils.getData('Popular Shots', `https://dribbble.com/shots${timeframe ? `?timeframe=${timeframe}` : ''}`); + const title = 'Dribbble - Popular Shots'; + + ctx.state.data = await utils.getData(ctx, url, title); }; diff --git a/lib/routes/dribbble/user.js b/lib/routes/dribbble/user.js index 69654feea0..4509b28fd0 100644 --- a/lib/routes/dribbble/user.js +++ b/lib/routes/dribbble/user.js @@ -2,6 +2,9 @@ const utils = require('./utils'); module.exports = async (ctx) => { const name = ctx.params.name; + const url = `https://dribbble.com/${name}`; - ctx.state.data = await utils.getData(name, `https://dribbble.com/${name}`); + const title = `Dribbble - user ${name}`; + + ctx.state.data = await utils.getData(ctx, url, title); }; diff --git a/lib/routes/dribbble/utils.js b/lib/routes/dribbble/utils.js index e785b7eebb..71321641d5 100644 --- a/lib/routes/dribbble/utils.js +++ b/lib/routes/dribbble/utils.js @@ -1,49 +1,84 @@ const got = require('@/utils/got'); const cheerio = require('cheerio'); +const url = require('url'); + +async function load(link) { + const response = await got.get(link); + const $ = cheerio.load(response.data); + + const shotMedia = $('.media-shot').html(); + const shotDescription = $('.shot-desc').html(); + + const description = `${shotMedia}
+ ${shotDescription}
+ ${$('.shot-views').text()}
+ ${$('.shot-likes').text()}
+ ${$('.shot-saves').text()}`; + + const pubDateString = $('.shot-date').text(); + const pubDate = new Date(pubDateString).toUTCString(); + + return { + description, + pubDate, + }; +} + +async function ProcessFeed(list, caches) { + const host = 'https://dribbble.com'; + + return await Promise.all( + list.map(async (item) => { + const $ = cheerio.load(item); + + const itemUrlPath = + $('.animated-target').attr('href') || + $('.extras > a') + .attr('href') + .replace('/rebounds', ''); + const itemUrl = url.resolve(host, itemUrlPath); + + const team = $('.attribution-team').text() ? ' for ' + $('.attribution-team a.url').text() : ''; + const author = 'by ' + $('.attribution-user a.url').text(); + + const single = { + title: $('.dribbble-over strong').text(), + link: itemUrl, + author: author + team, + guid: itemUrl, + }; + + const other = await caches.tryGet(itemUrl, async () => await load(itemUrl)); + + return Promise.resolve(Object.assign({}, single, other)); + }) + ); +} + +const getData = async (ctx, url, title) => { + const response = await got({ + method: 'get', + url: url, + headers: { + Referer: url, + }, + }); + + const data = response.data; + + const $ = cheerio.load(data); + const list = $('ol.dribbbles.group li.group').get(); + + const result = await ProcessFeed(list, ctx.cache); + + return { + title: title, + link: url, + description: $('meta[name="description"]').attr('content'), + item: result, + }; +}; module.exports = { - getData: async (name, url) => { - const response = await got({ - method: 'get', - url: url, - headers: { - Referer: url, - }, - }); - - const data = response.data; - - const $ = cheerio.load(data); - const list = $('ol.dribbbles.group li.group'); - - return { - title: `${name} - Dribbble`, - link: url, - description: $('meta[name="description"]').attr('content'), - item: - list && - list - .map((index, item) => { - item = $(item); - return { - title: item.find('.dribbble-over strong').text(), - description: `
- ${item.find('.comment').text()}
- Author: ${item.find('.attribution-team') ? item.find('.attribution-team').text() + ' -' : ''}${item.find('.attribution-user').text()}
- Views: ${item.find('.views').text()}
- Comment: ${item.find('.cmnt').text()}
- Favor: ${item.find('.fav').text()}`, - link: `https://dribbble.com${item.find('.animated-target').attr('href') || - item - .find('.extras > a') - .attr('href') - .replace('/rebounds', '')}`, - }; - }) - .get(), - }; - }, + getData, };