/** @module root/router */ 'use strict'; // vim: set ts=2 sw=2 et tw=80: const express = require('express'); const router = express.Router(); const mongoose = require('mongoose'); const Favorite = mongoose.model('Favorite'); const fetch = require('node-fetch'); const querystring = require('querystring'); const promiseAny = require('promise-any'); const eventBus = require('../../pubsub'); const fetch64 = require('fetch-base64'); router.get('/', (req, res) => { if (req.query.access_token) { req.app.locals.imgur = req.query; res.redirect('/'); } else { res.status(200, {'Content-Type': 'text/html'}); res.end(` `); } }); async function fetchImgur(req, res, method, url, body) { const endpoint = 'https://api.imgur.com/3'; const response = await fetch(endpoint + url, { method: method, headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization' : 'Bearer ' + req.app.locals.imgur.access_token }, body: body ? querystring.stringify(body) : undefined }); const json = await response.json(); if (json.status == 409 && url.match(/follow\/tag/)) { return {}; } if (Math.floor(json.status / 100) != 2) { res.status(json.status).json(json); return false; } return json; } router.post('/ordeal', async (req, res) => { try { if ((!req.body.replace && (!req.body.name || !req.body.album)) || (req.body.replace && (!req.body.name || !req.body.oldName))) { res.status(400).json({ error: "Malformed ordeal request" }); return; } const ordealResponse = { ordealSuccess: true }; const uploadData = { image: req.body.dataURL.substring('data:image/png;base64,'.length), type: 'base64', title: req.body.name, name: req.body.name + '.png', }; const uploadJson = await fetchImgur(req, res, 'POST', '/upload', uploadData); if (!uploadJson) { return; } const imageId = uploadJson.data.id; const albumData = { 'ids[]': imageId, }; if (!req.body.replace) { if (req.body.album) { albumData.title = req.body.album; } const albumJson = await fetchImgur(req, res, 'POST', '/album', albumData); if (!albumJson) { return; } if (req.body.favorites) { if (!await fetchImgur(req, res, 'POST', '/album/' + albumJson.data.id + '/favorite', {})) { return; } } } else { req.body.album = undefined; const submissions = await fetchImgur(req, res, 'GET', '/account/me/submissions'); if (!submissions) { return; } const submission = submissions.data .filter(e => !e.images && e.in_gallery && e.title == req.body.oldName)[0]; if (!submission) { res.status(404).json({ error: "No image in submissions found" }); return; } console.log('submission', submission.id, submission.title); const result = {}; result.image = submission; ordealResponse.views = submission.views; ordealResponse.votes = {}; ordealResponse.votes.ups = submission.ups; ordealResponse.votes.downs = submission.downs; const albumIds = await fetchImgur(req, res, 'GET', '/account/me/albums/ids'); if (!albumIds) { return; } console.log('albumIds', albumIds.data.join(',')); let reject = false; const promises = []; for (const albumId of albumIds.data) { promises.push(new Promise(async (res, rej) => { if (reject) { return reject; } const images = await fetchImgur(req, res, 'GET', '/album/' + albumId + '/images'); if (!images || reject) { rej(); return; } console.log('album', albumId, 'images', images.data.map(e => e.id)); const image = images.data.filter(e => e.id == result.image.id)[0]; if (!image || reject) { rej(); return; } reject = true; console.log('the album', albumId, 'image', image.id); res(albumId); })); } try { result.albumId = await promiseAny(promises); } catch(_) { res.status(400).json({ error: "Image not found in any album" }); return; } if (!await fetchImgur(req, res, 'DELETE', '/image/' + result.image.id)) { return; } if (!await fetchImgur(req, res, 'PUT', '/album/' + result.albumId + '/add', { 'ids[]': uploadJson.data.id })) { return; } } if (!await fetchImgur(req, res, 'POST', '/gallery/image/' + uploadJson.data.id, { title: req.body.name, tags: req.body.tags })) { return; } if (req.body.tags) { const tagsData = { 'tags': req.body.tags }; if (!await fetchImgur(req, res, 'POST', '/gallery/tags/' + uploadJson.data.id, tagsData)) { return; } for (const tag of req.body.tags.split(',')) { if (!await fetchImgur(req, res, 'POST', '/account/me/follow/tag/' + tag, {})) { return; } } } res.json(ordealResponse); } catch(e) { console.error(e); res.status(500).json({ error: e.toString() }); } }); router.post('/search', async (req, res) => { try { if (!req.body.name) { res.status(400).json({ error: 'Bad parameters for /imgur/search' }); return; } const results = await fetchImgur(req, res, 'GET', '/gallery/search/time/top/1?q=' + encodeURIComponent(req.body.name) + '&q_type=png'); if (!results) { return; } if (results.data.length == 0) { res.status(404).json({ error: 'No image found' }); return; } let image = results.data[0]; if (image.is_album) { image = image.images[0]; } if (!await fetchImgur(req, res, 'POST', '/gallery/' + results.data[0].id + '/vote/up', {})) { return; } if (!await fetchImgur(req, res, 'POST', '/image/' + image.id + '/favorite', {})) { return; } const fetch64res = await fetch64.remote(image.link); const fav = { _id: mongoose.Types.ObjectId(), name: req.body.name, dataURL: fetch64res[1], bookmarked: false, }; await new Favorite(fav).save(); eventBus.emit('favorite.created', fav); res.json({ success: true }); } catch(e) { console.error(e); res.status(500).json({ error: e.toString() }); } }); /** router for /root */ module.exports = router;