/
sourceNodes.js
86 lines (72 loc) 路 2.63 KB
/
sourceNodes.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import crypto from "crypto"
import fetch from "node-fetch"
import queryString from "query-string"
import createInstagramNode from "./createInstagramNode"
const defaultOptions = {
limit: Infinity,
pageLimit: 30
}
async function sourceNodes({ actions, createNodeId, getCache }, configOptions) {
const { createNode } = actions
delete configOptions.plugins
const config = { ...defaultOptions, ...configOptions }
const { limit } = config
const apiOptions = queryString.stringify({limit: config.pageLimit, access_token: config.access_token})
const apiUrl = `https://graph.instagram.com/me/media?fields=id,media_url,media_type,permalink,timestamp,caption,username,thumbnail_url,children{id,media_url,media_type,thumbnail_url,timestamp}&${apiOptions}`
// Helper function to fetch and parse data to JSON
const fetchAndParse = async (api) => {
const data = await fetch(api)
const response = await data.json()
return response
}
// Recursively get data from Instagram api
const getData = async (url, data = []) => {
let response = await fetchAndParse(url)
if (response.error !== undefined) {
console.error("\nINSTAGRAM API ERROR: ", response.error.message)
return data
}
data = data.concat(response.data)
let next_url = response?.paging?.next
if (data.length < limit && next_url) {
return getData(next_url, data)
}
return data
}
// Create nodes
const createNodes = async (API) => {
let data = await getData(API).then((res) => res)
if(data.length > limit) {
data = data.slice(0, limit)
}
for (const item of data) {
if (item.id !== undefined && ["IMAGE", "CAROUSEL_ALBUM", "VIDEO"].includes(item.media_type)) {
const nodeData = await processMedia(item)
createNode(nodeData)
}
}
}
// Processes a media to match Gatsby's node structure
const processMedia = async (media) => {
media.album = media.children && media.children.data.length && media.children.data.map((node) => node)
const nodeId = createNodeId(`instagram-media-${media.id}`)
const nodeContent = JSON.stringify(media)
const nodeContentDigest = crypto.createHash("md5").update(nodeContent).digest("hex")
const nodeData = Object.assign({}, media, {
id: nodeId,
media_id: media.id,
parent: null,
children: [],
internal: {
type: `InstagramContent`,
content: nodeContent,
contentDigest: nodeContentDigest,
},
})
// Create local image node
await createInstagramNode(nodeData, getCache, createNode, createNodeId)
return nodeData
}
return createNodes(apiUrl)
}
export default sourceNodes