HW7: winrking on 6

This commit is contained in:
Claudio Maggioni 2019-11-14 15:27:51 +01:00
parent 6f2d820fdd
commit d8efbdc8a9
7 changed files with 161 additions and 38 deletions

View file

@ -0,0 +1,30 @@
Nei giardini che nessuno sa - Renato NULL
Senti quella POST ruvida
Un gran freddo dentro l'anima
Fa fatica anche una GET a scendere giù
Troppe await dietro l'angolo
{success: true} che non ti appartengono
Questo OAuth inconciliabile gioca contro di te
Ecco come si finisce poi
In catch e console.error noi
Spettatori malinconici di j-j-javascript impossibili
Tanti bonus rimandati e gia'
Response vuote da un'eternità
Quella throw che non sai cos'è
Solo lei non ti abbandonerà... mai, oh mai
Ti darei i sorgenti per far fetch come non sai
L'energia, l'allegria per yarn start e yarn run dustc
Dirti due, sempre due-cento e farti eseguire
Dove vuoi, dove sai senza più quel JSON sul cuore
Nasconderti gli errori, quel server node sul tereh-rminale
Curarti le ferite e poi qualche log in più per testare
E poi vederti terminar e poi vederti ritornar ora
Dimentica, c'è chi dimentica distrattamente un for una domenica
E poi silenzi
E poi silenzi
Silenzi

View file

@ -29,6 +29,7 @@
"mongoose": "^5.7.7", "mongoose": "^5.7.7",
"morgan": "^1.9.0", "morgan": "^1.9.0",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"promise-any": "^0.2.0",
"request": "^2.88.0", "request": "^2.88.0",
"socket.io": "^2.3.0", "socket.io": "^2.3.0",
"supertest": "^3.0.0" "supertest": "^3.0.0"

View file

@ -2,9 +2,9 @@
class App { class App {
static get BRUSHES() { static get BRUSHES() {
return { return {
"PenBrush": new PenBrush(), 'PenBrush': new PenBrush(),
"DiscBrush": new DiscBrush(), 'DiscBrush': new DiscBrush(),
"StarBrush": new StarBrush(), 'StarBrush': new StarBrush(),
}; };
} }
@ -14,13 +14,25 @@ class App {
socketSessionId = null; socketSessionId = null;
registerFavoriteEvents(_id, dom) { registerFavoriteEvents(_id, dom) {
const imgurForm = dom.querySelector('form.favorites'); const imgurForm = dom.querySelector('form.favorites');
const replaceToggle = dom.querySelector('input[name=replace]');
const albumInput = imgurForm.querySelector('input[name=album]');
const replacePanel = imgurForm.querySelector('.replace');
dom.querySelector('button.imgur').onclick = () => { dom.querySelector('button.imgur').onclick = () => {
imgurForm.classList.toggle('hidden'); imgurForm.classList.toggle('hidden');
}; };
replaceToggle.onclick = () => {
if (replaceToggle.checked) {
replacePanel.classList.remove('hidden');
albumInput.setAttribute('disabled', 'disabled');
} else {
replacePanel.classList.add('hidden');
albumInput.removeAttribute('disabled');
}
};
imgurForm.onsubmit = e => { imgurForm.onsubmit = e => {
imgurForm.classList.remove('ok'); imgurForm.classList.remove('ok');
imgurForm.classList.remove('err'); imgurForm.classList.remove('err');
@ -30,11 +42,14 @@ class App {
const obj = { const obj = {
dataURL: data.get('dataURL'), dataURL: data.get('dataURL'),
name: dom.querySelector('form.data input[name=name]').value, name: dom.querySelector('form.data input[name=name]').value,
replace: data.get('replace'),
oldName: data.get('old_name'),
album: data.get('album'), album: data.get('album'),
tags: data.get('tags'), tags: data.get('tags'),
favorites: data.get('favorites') favorites: data.get('favorites')
}; };
doJSONRequest('POST', '/imgur/ordeal', {}, obj) doJSONRequest('POST', '/imgur/ordeal', {}, obj)
.then(e => { .then(e => {
if (e.ordealSuccess === true) { if (e.ordealSuccess === true) {
@ -52,7 +67,7 @@ class App {
const delay = (f, ...args) => { const delay = (f, ...args) => {
const execute = (f, ...args) => { const execute = (f, ...args) => {
console.log("don't delay, solve Carzaniga today", ...args); console.log('don\'t delay, solve Carzaniga today', ...args);
this.render_timestamp = new Date().getTime(); this.render_timestamp = new Date().getTime();
this.render_timeout = null; this.render_timeout = null;
this.render_last = null; this.render_last = null;
@ -60,7 +75,7 @@ class App {
}; };
if (new Date().getTime() - this.render_timestamp < 100000) { if (new Date().getTime() - this.render_timestamp < 100000) {
console.log("delaying", ...args); console.log('delaying', ...args);
this.render_last = () => execute(f, ...args); this.render_last = () => execute(f, ...args);
if (this.render_timeout === null) { if (this.render_timeout === null) {
this.render_timeout = setTimeout(() => this.render_last(), 100); this.render_timeout = setTimeout(() => this.render_last(), 100);
@ -190,20 +205,20 @@ class App {
const socket = io(); const socket = io();
socket.on('connect', () => { socket.on('connect', () => {
console.log("Socket connected"); console.log('Socket connected');
}); });
socket.on('sessionId', (msg) => { socket.on('sessionId', (msg) => {
console.log("Socket session id is", msg.id); console.log('Socket session id is', msg.id);
this.socketSessionId = msg.id; this.socketSessionId = msg.id;
}); });
socket.on('disconnect', (reason) => { socket.on('disconnect', (reason) => {
console.log("Socket disconnected"); console.log('Socket disconnected');
}); });
socket.on('reconnect', (attemptNumber) => { socket.on('reconnect', (attemptNumber) => {
console.log("Socket reconnected"); console.log('Socket reconnected');
}); });
socket.on('favorite.created', (msg) => { socket.on('favorite.created', (msg) => {
@ -287,7 +302,7 @@ class App {
bookmarked: false bookmarked: false
}; };
doJSONRequest("POST", "/favorites?socketid=" + this.socketSessionId, doJSONRequest('POST', '/favorites?socketid=' + this.socketSessionId,
{}, data) {}, data)
.then(data => this.renderFavorite(data, 'top')) .then(data => this.renderFavorite(data, 'top'))
.catch(console.error); .catch(console.error);
@ -332,7 +347,7 @@ class App {
this.ctx.lineWidth = 1; this.ctx.lineWidth = 1;
this.strokeStyle = this.constructor.defaultStrokeStyle; this.strokeStyle = this.constructor.defaultStrokeStyle;
this.brush = "PenBrush"; this.brush = 'PenBrush';
const brushToolbar = document.querySelector('#brush-toolbar'); const brushToolbar = document.querySelector('#brush-toolbar');
if (brushToolbar) { if (brushToolbar) {

View file

@ -118,6 +118,7 @@ body {
margin: 5px; margin: 5px;
float: left; float: left;
width: 200px; width: 200px;
font-size: 0.7em;
} }
#favourites img { #favourites img {
@ -131,3 +132,15 @@ body {
padding: 15px; padding: 15px;
text-align: center; text-align: center;
} }
.hidden {
display: none;
}
.ok {
background-color: lightgreen;
}
.err {
background-color: pink;
}

View file

@ -9,6 +9,7 @@ const mongoose = require('mongoose');
const Favorite = mongoose.model('Favorite'); const Favorite = mongoose.model('Favorite');
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const querystring = require('querystring'); const querystring = require('querystring');
const promiseAny = require('promise-any');
const { error } = require('../utils'); const { error } = require('../utils');
@ -41,29 +42,29 @@ router.get('/imgur', (req, res) => {
async function fetchImgur(req, res, method, url, body) { async function fetchImgur(req, res, method, url, body) {
const endpoint = 'https://api.imgur.com/3'; const endpoint = 'https://api.imgur.com/3';
const uploadRes = await fetch(endpoint + url, { const response = await fetch(endpoint + url, {
method: method, method: method,
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
'Authorization' : 'Bearer ' + req.app.locals.imgur.access_token 'Authorization' : 'Bearer ' + req.app.locals.imgur.access_token
}, },
body: querystring.stringify(body) body: body ? querystring.stringify(body) : undefined
}); });
const uploadJson = await uploadRes.json(); const json = await response.json();
if (Math.floor(uploadJson.status / 100) != 2) { if (Math.floor(json.status / 100) != 2) {
res.status(uploadJson.status).json(uploadJson); res.status(json.status).json(json);
return false; return false;
} }
console.log(url, uploadJson); return json;
return uploadJson;
} }
router.post('/imgur/ordeal', async (req, res) => { router.post('/imgur/ordeal', async (req, res) => {
try { try {
const ordealResponse = { ordealSuccess: true };
const uploadData = { const uploadData = {
image: req.body.dataURL.substring('data:image/png;base64,'.length), image: req.body.dataURL.substring('data:image/png;base64,'.length),
type: 'base64', type: 'base64',
@ -81,11 +82,13 @@ router.post('/imgur/ordeal', async (req, res) => {
'ids[]': imageId, 'ids[]': imageId,
}; };
let albumJson;
if (!req.body.replace) {
if (req.body.album) { if (req.body.album) {
albumData.title = req.body.album; albumData.title = req.body.album;
} }
const albumJson = await fetchImgur(req, res, 'POST', '/album', albumData); albumJson = await fetchImgur(req, res, 'POST', '/album', albumData);
if (!albumJson) { if (!albumJson) {
return; return;
} }
@ -97,6 +100,61 @@ router.post('/imgur/ordeal', async (req, res) => {
return; return;
} }
} }
} else {
req.body.album = undefined;
const albums = await fetchImgur(req, res, 'GET', '/account/me/albums');
if (!albums) {
return;
}
console.log('albums', albums.data.length);
let reject = false;
const promises = [];
for (const album of albums.data) {
promises.push(new Promise(async (res, rej) => {
if (reject) {
return reject;
}
const images = await fetchImgur(req, res, 'GET', '/album/' + album.id +
'/images');
if (!images || reject) {
rej();
return;
}
const image =
images.data.filter(e => e.name.match(req.body.oldName))[0];
if (!image || reject) {
rej();
return;
}
reject = true;
res({ album: album, image: image });
}));
}
const result = await promiseAny(promises);
albumJson = { data: result.album };
ordealResponse.views = result.image.views;
ordealResponse.votes = await fetchImgur(req, res, 'GET', '/gallery/'
+ result.image.id + '/votes');
if (!await fetchImgur(req, res, 'DELETE', '/image/' + result.image.id)) {
return;
}
if (!await fetchImgur(req, res, 'PUT', '/album/' + result.album.id +
'/add', { 'ids[]': uploadJson.data.id })) {
return;
}
}
if (!await fetchImgur(req, res, 'POST', '/gallery/album/' + if (!await fetchImgur(req, res, 'POST', '/gallery/album/' +
albumJson.data.id, { title: req.body.album ? req.body.album : albumJson.data.id, { title: req.body.album ? req.body.album :
@ -122,7 +180,7 @@ router.post('/imgur/ordeal', async (req, res) => {
} }
} }
res.json({ordealSuccess: true}); res.json(ordealResponse);
} catch(e) { } catch(e) {
console.error(e); console.error(e);
res.status(500).json(e); res.status(500).json(e);

View file

@ -1,9 +1,5 @@
{! vim: set ts=2 sw=2 et tw=120: !} {! vim: set ts=2 sw=2 et tw=120: !}
<style>.hidden {display: none}
.ok {background-color: lightgreen}
.err {background-color: pink}</style>
<h3>{name}</h3> <h3>{name}</h3>
<img src="{dataURL}" alt="{name}"> <img src="{dataURL}" alt="{name}">
{?b} {?b}
@ -35,7 +31,12 @@ formaction="/favorites/{_id}/bookmarked?_method=PUT">Add bookmark</button>
<input type="text" name="album" placeholder="Imgur album name"><br> <input type="text" name="album" placeholder="Imgur album name"><br>
<input type="text" name="tags" placeholder="Imgur tags"><br> <input type="text" name="tags" placeholder="Imgur tags"><br>
<label for="favorites">Add in favorites</label> <label for="favorites">Add in favorites</label>
<input type="checkbox" name="favorites"> <input type="checkbox" name="favorites"><br>
<button>Submit</button> <label for="favorites">Replace an image</label>
<input type="checkbox" name="replace"><br>
<div class="replace hidden">
<input type="text" name="old_name" required placeholder="Imgur image name to replace"><br>
</div>
<button>Submit to Imgur</button>
</form> </form>
{/details} {/details}

View file

@ -1830,6 +1830,11 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
promise-any@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/promise-any/-/promise-any-0.2.0.tgz#7aeaafd6297698d8874cb7d3bc7c0faf89fffe8a"
integrity sha1-euqv1il2mNiHTLfTvHwPr4n//oo=
proxy-addr@~2.0.5: proxy-addr@~2.0.5:
version "2.0.5" version "2.0.5"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34"