diff --git a/docs/en/new-media.md b/docs/en/new-media.md
index f24616830..d2e02f828 100644
--- a/docs/en/new-media.md
+++ b/docs/en/new-media.md
@@ -156,14 +156,7 @@ Provides a better reading experience (full text articles) over the official one.
## Vulture
-
-
-Supported sub-sites:
-| TV | Movies | Comedy | Music | TV Recaps | Books | Theater | Art | Awards | Video |
-| --- | ------ | ------ | ----- | --------- | ----- | ------- | --- | ------ | ----- |
-| tv | movies | comedy | music | tvrecaps | books | theater | art | awards | video |
-
-
+
## World Health Organization | WHO
diff --git a/lib/router.js b/lib/router.js
index b4de6a00d..c5e1c04d6 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -2215,7 +2215,7 @@ router.get('/mastodon/timeline/:site/:only_media?', require('./routes/mastodon/t
router.get('/aliyun-kernel/index', require('./routes/aliyun-kernel/index'));
// Vulture
-router.get('/vulture/:type/:excludetags?', require('./routes/vulture/index'));
+router.get('/vulture/:tag/:excludetags?', require('./routes/vulture/index'));
// xinwenlianbo
router.get('/xinwenlianbo/index', require('./routes/xinwenlianbo/index'));
diff --git a/lib/routes/vulture/index.js b/lib/routes/vulture/index.js
index 45d8957c3..789b45eaf 100644
--- a/lib/routes/vulture/index.js
+++ b/lib/routes/vulture/index.js
@@ -1,9 +1,14 @@
const utils = require('./utils');
module.exports = async (ctx) => {
- const url = `https://www.vulture.com/${ctx.params.type}/`;
- const title = `Vulture - ${ctx.params.type}`;
+ const url = `https://www.vulture.com/news/${ctx.params.tag}/`;
const tagsToExclude = ctx.params.excludetags;
+ let title = `Vulture - tag ${ctx.params.tag}`;
+ if (tagsToExclude !== undefined) {
+ title += ' - excluding tags ';
+ title += tagsToExclude.split(',').join(', ');
+ }
+
ctx.state.data = await utils.getData(ctx, url, title, tagsToExclude);
};
diff --git a/lib/routes/vulture/utils.js b/lib/routes/vulture/utils.js
index ae3944686..a3b32dcb1 100644
--- a/lib/routes/vulture/utils.js
+++ b/lib/routes/vulture/utils.js
@@ -1,10 +1,17 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
-async function load(link) {
- const response = await got.get(link);
+async function load(articleURL) {
+ const response = await got.get(articleURL);
const $ = cheerio.load(response.data);
+ // get the metadata
+ const title = $('meta[property="og:title"]').attr('content');
+ const pubDate = $('meta[property="article:published_time"]').attr('content');
+ const bylineString = 'by ' + $('meta[name="author"]').attr('content');
+ const tags = $('meta[property="article:tag"]').attr('content').split(', ');
+
+ // get the contents of the article
const description = $('div.article-content');
// remove the content that we don't want to show
@@ -16,45 +23,44 @@ async function load(link) {
description.find('div.mobile-secondary-area').remove();
description.find('aside.newsletter-flex-text').remove();
- // get the tags
- const tagElements = $('div.tags > ul > li > a:not(.more)');
- const tags = tagElements
- .map(function () {
- return $(this).text().toLowerCase();
- })
- .get();
+ // add the tags to the end
+ description.append('
tags: ' + tags.join(', '));
return {
+ title: title,
+ author: bylineString,
+ pubDate: pubDate,
+ link: articleURL,
+ guid: articleURL,
description: description.html(),
tags: tags,
};
}
-async function ProcessFeed(list, caches) {
+async function ProcessFeed(htmlData, caches) {
+ const $ = cheerio.load(htmlData);
+ const allArticles = $('section.paginated-feed li.article');
+
+ // limit the list to only 25 articles, to make sure that load times remain reasonable
+ const articles = allArticles.slice(0, 25);
+
+ const articleURLs = [];
+ $(articles).each(function (index, article) {
+ const articleLink = $(article).find('a.link-text');
+
+ let articleURL = articleLink.attr('href');
+ if (articleURL.startsWith('//www.')) {
+ articleURL = 'https:' + articleURL;
+ } else if (articleURL.startsWith('www.')) {
+ articleURL = 'https://' + articleURL;
+ }
+ articleURLs.push(articleURL);
+ });
+
return await Promise.all(
- list.map(async (item) => {
- const itemUrl = item.canonicalUrl;
-
- let bylineString = '';
- if (item.byline) {
- const byline = item.byline[0];
- const bylineNames = byline.names.map((name) => name.text);
- const bylineNamesString = bylineNames.join(', ');
-
- bylineString = 'by ' + bylineNamesString;
- }
-
- const single = {
- title: item.primaryHeadline,
- link: itemUrl,
- author: bylineString,
- guid: itemUrl,
- pubDate: item.date,
- };
-
- const other = await caches.tryGet(itemUrl, async () => await load(itemUrl));
-
- return Promise.resolve(Object.assign({}, single, other));
+ articleURLs.map(async (articleURL) => {
+ const data = await caches.tryGet(articleURL, async () => await load(articleURL));
+ return Promise.resolve(Object.assign({}, data));
})
);
}
@@ -82,29 +88,7 @@ const getData = async (ctx, url, title, tagsToExclude) => {
});
const htmlData = htmlResponse.data;
-
- const $ = cheerio.load(htmlData);
- let dataUri = $('section.paginated-feed').attr('data-uri');
-
- if (dataUri.startsWith('www.')) {
- dataUri = 'https://' + dataUri;
- }
-
- // get the raw data
- const response = await got({
- method: 'get',
- url: dataUri,
- headers: {
- Referer: dataUri,
- },
- });
-
- const data = response.data;
-
- // limit the list to only 25 articles, to make sure that load times remain reasonable
- const list = data.articles.slice(0, 25);
-
- let result = await ProcessFeed(list, ctx.cache);
+ let result = await ProcessFeed(htmlData, ctx.cache);
// filter out specified tags
if (tagsToExclude !== undefined) {
@@ -112,10 +96,14 @@ const getData = async (ctx, url, title, tagsToExclude) => {
result = FilterItemsWithTags(result, tagsToExcludeArray);
}
+ // get the description
+ const $ = cheerio.load(htmlData);
+ const description = $('meta[name="description"]').attr('content');
+
return {
title: title,
link: url,
- description: $('meta[name="description"]').attr('content'),
+ description: description,
item: result,
};
};