add: instagram/tag (#1964)

add support to fetch instagram's hashtags. eg:
* [#designertoys](https://www.instagram.com/explore/tags/designertoys/)
* [#urbantoys](https://www.instagram.com/explore/tags/urbantoys/)
This commit is contained in:
Dewa M. Widyakumara
2019-04-21 16:52:05 +07:00
committed by DIYgod
parent ab6334b01d
commit b31d4edd72
3 changed files with 112 additions and 0 deletions

View File

@@ -225,6 +225,8 @@ If no matching results were found, the server returns only a HTTP status code `2
<RouteEn name="User" path="/instagram/user/:id" example="/instagram/user/diygod" :paramsDesc="['Instagram id']" />
<RouteEn name="Hashtag" author="widyakumara" path="/instagram/tag/:tag" example="/instagram/tag/urbantoys" :paramsDesc="['Instagram hashtag']" />
### Youtube
<RouteEn name="User" path="/youtube/user/:username/:embed?" example="/youtube/user/JFlaMusic" :paramsDesc="['YouTuber id', 'Default to embed the video, set to any value to disable embedding']" />

View File

@@ -258,6 +258,7 @@ if (config.twitter && config.twitter.consumer_key && config.twitter.consumer_sec
// Instagram
router.get('/instagram/user/:id', require('./routes/instagram/user'));
router.get('/instagram/tag/:tag', require('./routes/instagram/tag'));
// Youtube
if (config.youtube && config.youtube.key) {

109
lib/routes/instagram/tag.js Normal file
View File

@@ -0,0 +1,109 @@
const axios = require('../../utils/axios');
const cheerio = require('cheerio');
module.exports = async (ctx) => {
const tag = ctx.params.tag;
const response = await axios({
method: 'get',
url: `https://www.instagram.com/explore/tags/${tag}/`,
headers: {
Referer: `https://www.instagram.com/explore/tags/${tag}/`,
},
});
const data = JSON.parse(response.data.match(/<script type="text\/javascript">window._sharedData = (.*);<\/script>/)[1]) || {};
const list = data.entry_data.TagPage[0].graphql.hashtag.edge_hashtag_to_media.edges;
const $ = cheerio.load(response.data);
// retrieve media objects
const media = await Promise.all(
list.map(async (item) => {
item = item.node;
const url = `https://www.instagram.com/p/${item.shortcode}`;
const cache = await ctx.cache.get(url);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
if (item.__typename === 'GraphImage') {
const single = {
image: item.display_url,
};
ctx.cache.set(url, JSON.stringify([single]), 24 * 60 * 60);
return Promise.resolve([single]);
} else if (item.__typename === 'GraphSidecar') {
const response = await axios({
method: 'get',
url,
});
const data = JSON.parse(response.data.match(/<script type="text\/javascript">window._sharedData = (.*);<\/script>/)[1]) || {};
const single = data.entry_data.PostPage[0].graphql.shortcode_media.edge_sidecar_to_children.edges.map((item) => ({
image: item.node.display_url,
video: item.node.video_url,
}));
ctx.cache.set(url, JSON.stringify(single), 24 * 60 * 60);
return Promise.resolve(single);
} else if (item.__typename === 'GraphVideo') {
const response = await axios({
method: 'get',
url,
});
const data = JSON.parse(response.data.match(/<script type="text\/javascript">window._sharedData = (.*);<\/script>/)[1]) || {};
const single = {
image: data.entry_data.PostPage[0].graphql.shortcode_media.display_url,
video: data.entry_data.PostPage[0].graphql.shortcode_media.video_url,
};
ctx.cache.set(url, JSON.stringify([single]), 24 * 60 * 60);
return Promise.resolve([single]);
}
})
);
ctx.state.data = {
title: `#${tag} hashtag on Instagram`,
link: `https://www.instagram.com/explore/tags/${tag}/`,
description: $('meta[name="description"]').attr('content'),
item: list.map((item, index) => {
item = item.node;
let image = 0;
let video = 0;
let content = '';
for (let i = 0; i < media[index].length; i++) {
if (media[index][i].image) {
content += `<img referrerpolicy="no-referrer" src="${media[index][i].image}"><br>`;
image++;
}
if (media[index][i].video) {
content += `<video width="100%" controls="controls"> <source src="${media[index][i].video}" type="video/mp4"> Your RSS reader does not support video playback. </video>`;
video++;
}
}
let title = (item.edge_media_to_caption.edges && item.edge_media_to_caption.edges[0] && item.edge_media_to_caption.edges[0].node.text) || '无题/Untitled';
if (image > 1) {
title = `[组图/Carousel]${title}`;
}
if (video > 0) {
title = `[视频/Video]${title}`;
}
return {
title: `${title}`,
description: `${title}<br>${content}`,
pubDate: new Date(item.taken_at_timestamp * 1000).toUTCString(),
link: `https://www.instagram.com/p/${item.shortcode}/`,
};
}),
};
};