|
| 1 | +require("@babel/polyfill"); |
| 2 | +const fetch = require("node-fetch"); |
| 3 | +const queryString = require("query-string"); |
| 4 | + |
| 5 | +exports.sourceNodes = async ( |
| 6 | + { boundActionCreators: { createNode }, createNodeId, createContentDigest }, |
| 7 | + { plugins, ...options } |
| 8 | +) => { |
| 9 | + const sizes = ["sq", "t", "s", "q", "m", "n", "z,", "c", "l", "z"]; |
| 10 | + |
| 11 | + // The flickr API has some issues when put into GraphQL - create a suitable version |
| 12 | + const fixPhoto = photo => { |
| 13 | + const fixed = photo; |
| 14 | + |
| 15 | + // Don't name crash with node.id |
| 16 | + fixed.photo_id = fixed.id; |
| 17 | + delete fixed.id; |
| 18 | + |
| 19 | + // Some fields can come down as either string or number. GraphQL doesn't like that. Force everything to number |
| 20 | + |
| 21 | + sizes.forEach(suffix => { |
| 22 | + if (fixed.hasOwnProperty(`height_${suffix}`)) { |
| 23 | + fixed[`height_${suffix}`] = parseInt(fixed[`height_${suffix}`]); |
| 24 | + } |
| 25 | + if (fixed.hasOwnProperty(`width_${suffix}`)) { |
| 26 | + fixed[`width_${suffix}`] = parseInt(fixed[`width_${suffix}`]); |
| 27 | + } |
| 28 | + }); |
| 29 | + |
| 30 | + if (fixed.hasOwnProperty("accuracy")) { |
| 31 | + fixed.accuracy = parseInt(fixed.accuracy); |
| 32 | + } |
| 33 | + |
| 34 | + // A missing latitude or longitude can come down as either 0 or "0" - force to string |
| 35 | + |
| 36 | + if (fixed.hasOwnProperty("latitude")) { |
| 37 | + fixed.latitude = "" + fixed.latitude; |
| 38 | + } |
| 39 | + if (fixed.hasOwnProperty("longitude")) { |
| 40 | + fixed.longitude = "" + fixed.longitude; |
| 41 | + } |
| 42 | + |
| 43 | + // These can come down as either string or number. Have only ever seen "0" and 0 here - and documentation is sparse - remove them |
| 44 | + |
| 45 | + if (fixed.hasOwnProperty("datetakengranularity")) { |
| 46 | + delete fixed.datetakengranularity; |
| 47 | + } |
| 48 | + if (fixed.hasOwnProperty("datetakenunknown")) { |
| 49 | + delete fixed.datetakenunknown; |
| 50 | + } |
| 51 | + |
| 52 | + // Convert Date versions of dateupload and lastupdate |
| 53 | + |
| 54 | + if (fixed.hasOwnProperty("dateupload")) { |
| 55 | + fixed.dateupload_date = new Date(fixed.dateupload * 1000); |
| 56 | + } |
| 57 | + if (fixed.hasOwnProperty("lastupdate")) { |
| 58 | + fixed.lastupdate_date = new Date(fixed.lastupdate * 1000); |
| 59 | + } |
| 60 | + |
| 61 | + // Simplify the structure of the description to just a string |
| 62 | + |
| 63 | + if (fixed.hasOwnProperty("description")) { |
| 64 | + if (fixed.description.hasOwnProperty("_content")) { |
| 65 | + fixed.description = fixed.description._content; |
| 66 | + } |
| 67 | + } |
| 68 | + |
| 69 | + return fixed; |
| 70 | + }; |
| 71 | + |
| 72 | + const url = `https://api.flickr.com/services/rest/?${queryString.stringify({ |
| 73 | + method: "flickr.photos.search", |
| 74 | + extras: |
| 75 | + "description, license, date_upload, date_taken, owner_name, icon_server, original_format, last_update, geo, tags, machine_tags, o_dims, views, media, path_alias, url_sq, url_t, url_s, url_q, url_m, url_n, url_z, url_c, url_l, url_o", |
| 76 | + per_page: 500, |
| 77 | + format: "json", |
| 78 | + nojsoncallback: 1, |
| 79 | + ...options |
| 80 | + })}`; |
| 81 | + |
| 82 | + const response = await fetch(url); |
| 83 | + const data = await response.json(); |
| 84 | + |
| 85 | + data.photos.photo.forEach(raw => { |
| 86 | + const photo = fixPhoto(raw); |
| 87 | + |
| 88 | + createNode({ |
| 89 | + ...photo, |
| 90 | + id: createNodeId(`flickr-photo-${photo.photo_id}`), |
| 91 | + parent: null, |
| 92 | + children: [], |
| 93 | + internal: { |
| 94 | + type: "FlickrPhoto", |
| 95 | + content: JSON.stringify(photo), |
| 96 | + contentDigest: createContentDigest(photo) |
| 97 | + } |
| 98 | + }); |
| 99 | + }); |
| 100 | +}; |
0 commit comments