Как-то раз, за обсуждением Idris ЯП с коллегой, зашла речь про графики plotly. Очередное подделие вызвало у меня неподдельную усмешку. Ещё бы! Что можно ожидать от ещё одного велосипедного чарта, содержащего в себе d3 и webgl? Правильно, валялся бы этот велосипед в бездне гитхаба, если бы у меня получилось установить chartjs-node. Но что-то мой химерный ubuntu-windows терминал, о котором я как раз недавно сделал обзор на моё блоге, не давал пакету установится, выплёвывая свою ругань на node-gyp. Python'ячьи ошибки не забота фронтмэна! Подакдакав, нашёл nodejs враппер plotly, под платный REST-API сервис https://plot.ly/, у которого по нынешним маркетинговым уловкам, конечно же был OpenSource вариант. Он то мне и подошёл. Прицепив его к своему простенькому боту всё было здорово, пока не вспомнилось что бэкэнд бота лежит на Heroku, а там фишка с fs.createWriteStream() не срабатывает по понятным знатоку SaSS-причинам. Задача вроде плёвая: из результата POST-запроса достать res: https.request(options, function handleResponse(res) { if (res.statusCode !== 200) { callback(null, res); }); var fileStream = fs.createWriteStream('1.png'); imageStream.pipe(fileStream); Без моих знаний о стримах понимать что происходит было сложно, типичный кейс с Stack Overflow Driven Development не прокатывал, потому что Stackoverflow уже был засран этим нубским говнищем, и искать что-либо нормальное было нереально. Потому залип в нодовские доки, чтобы понять как работают эти их хитрые стримы. Скажу, они работают круто, но сложно. Всякие пайпы, события close, end и разделение на секции Readable и Writable. Итогом стал нижеследующий код, смысл которого в том, чтобы через Writable стрим запайпить тот самый imageStream, данные которого можно будет прочитать в ws._write через чанк. Главная трабла, что привычный механизм добавления чанков через строковую переменную здесь не работает, важно обязательно добавлять невредимый чанк в своем формает Int8Array. Я это сделал через buffers. Затем у imageStream появляется возможность уловить события end в котором складываем все собранные чанки в один буфер и посылаем куда следует. const Writable = stream.Writable; const ws = Writable(); const buffers = []; ws._write = (chunk, enc, next) => { buffers.push(chunk); next(); }; imageStream.pipe(ws); imageStream.on('end', () => { const photoBuffer = Buffer.concat(buffers); return bot.sendPhoto(chatId, photoBuffer, { caption: 'Photo' }); }); |
Новости >