From ae27890ff7d11a2c10189ae562a772b4d6f88e96 Mon Sep 17 00:00:00 2001 From: "Glitch (fediverse-bot)" Date: Fri, 11 Sep 2020 19:18:22 +0000 Subject: [PATCH] Cleanup. --- bot/bot.js | 20 ++++-- bot/script.js | 24 +++---- generators/joy-division.js | 119 ++++++++++++++++++++++++++++++++ generators/triangular-mesh.js | 123 ---------------------------------- helpers/colorbrewer.js | 72 ++++++++++++++++++++ server.js | 15 +++-- views/home.handlebars | 11 +-- views/post.handlebars | 6 +- 8 files changed, 237 insertions(+), 153 deletions(-) create mode 100644 generators/joy-division.js delete mode 100644 generators/triangular-mesh.js create mode 100644 helpers/colorbrewer.js diff --git a/bot/bot.js b/bot/bot.js index 1be3719..47d59ec 100644 --- a/bot/bot.js +++ b/bot/bot.js @@ -213,8 +213,8 @@ else{ let bot = this, guid = crypto.randomBytes(16).toString( 'hex' ); - dbHelper.getEvent(payload.id, function( err, data ){ - // console.log( 'getEvent', err, data ); + dbHelper.getEvent(payload.id, function( err, eventData ){ + console.log( 'getEvent', err, eventData ); bot.signAndSend( { @@ -229,11 +229,17 @@ else{ 'object': payload, } }, function( err, data ){ - if ( cb ){ - cb( err, payload, data ); - } - console.log( 'saving event', payload.id) - dbHelper.saveEvent(payload.id ); + if ( eventData ){ + err = 'duplicate event'; + console.log( 'error: duplicate event' ); + } else { + console.log( 'saving event', payload.id ); + dbHelper.saveEvent( payload.id ); + } + + if ( cb ){ + cb( err, payload, data ); + } } ); } ); diff --git a/bot/script.js b/bot/script.js index 7020f3a..8eefcd6 100644 --- a/bot/script.js +++ b/bot/script.js @@ -1,8 +1,9 @@ const express = require( 'express' ), helpers = require( __dirname + '/../helpers/general.js' ), ColorScheme = require('color-scheme'), + colorbrewerColors = require( __dirname + '/../helpers/colorbrewer.js' ), generators = { - triangular_mesh: require(__dirname + '/../generators/triangular-mesh.js') + joy_division: require(__dirname + '/../generators/joy-division.js') }, grammar = require( __dirname + '/../tracery/tracery.js' ).grammar; @@ -17,22 +18,21 @@ module.exports = function(){ .scheme( 'mono' ) .variation( 'soft' ); - generators.triangular_mesh( { - width: 800, - height: 360, - colors: scheme.colors() - }, function( err, imgData ){ - const imgUrl = `${ bot.bot_url }/${ imgData.path }`; - console.log( 'posting new image...', imgUrl ); - - var imgName = imgData.path.replace( 'img/', '' ); + generators.joy_division( { + width: 640, + height: 480, + colors: helpers.randomFromArray( colorbrewerColors ), + animate: true, + save: true + }, function( err, imgURL ){ + console.log( 'posting new image...', imgURL ); bot.createPost( { type: 'Note', - content: content, + // content: content, attachment: [ { - url: imgUrl, + url: imgURL, content: content // Image description here. } ] diff --git a/generators/joy-division.js b/generators/joy-division.js new file mode 100644 index 0000000..aad899a --- /dev/null +++ b/generators/joy-division.js @@ -0,0 +1,119 @@ +const fs = require( 'fs' ), + crypto = require('crypto'), + Canvas = require( 'canvas' ), + GIFEncoder = require( 'gifencoder' ), + concat = require( 'concat-stream' ), + helpers = require(__dirname + '/../helpers/general.js'), + imgFolder = './.data/img'; + + const filePath = `${ imgFolder }/${ helpers.getTimestamp() }-${ crypto.randomBytes( 4 ).toString( 'hex' ) }`, + filePathGIF = `${ filePath }.gif`, + filePathPNG = `${ filePath }.png`, + fileUrl = `https://${ process.env.PROJECT_DOMAIN }.glitch.me/${ filePath.replace( './.data/', '' ) }`, + fileUrlGIF = `${ fileUrl }.gif`, + fileUrlPNG = `${ fileUrl }.png`; + +module.exports = function( options, cb ) { + /* + Based on http://generativeartistry.com/tutorials/joy-division/ + */ + console.log( 'making waves...' ); + let width = options.width || 640, + height = options.height || 480, + colors = options.colors || ['000', 'fff'], + canvas = Canvas.createCanvas( width, height ), + ctx = canvas.getContext( '2d' ), + encoder; + + if ( options.animate ){ + encoder = new GIFEncoder( width, height ); + + + if ( options.save ){ + encoder.createReadStream().pipe( fs.createWriteStream( filePathGIF ) ); + } else { + encoder.createReadStream().pipe( concat( ( data ) => { + if ( cb ){ + cb( null, data.toString( 'base64' ) ); + } + } ) ); + } + + encoder.start(); + encoder.setRepeat( 0 ); // 0 for repeat, -1 for no-repeat + encoder.setDelay( 100 ); // frame delay in milliseconds + encoder.setQuality( 10 ); // image quality, 10 is default. + } + + ctx.lineWidth = helpers.getRandomInt( 1,4 ); + ctx.fillStyle = colors[0]; + ctx.strokeStyle = colors[1]; + ctx.fillRect( 0, 0, canvas.width, canvas.height ); + + if ( options.animate ){ + encoder.addFrame( ctx ); + } + + let step = helpers.getRandomInt( 8, 12 ); + let lines = []; + + // Create the lines + for ( let i = step; i <= height - step; i += step ) { + + let line = []; + for ( let j = step; j <= height - step; j+= step ) { + let distanceToCenter = Math.abs( j - height / 2 ); + let variance = Math.max( height / 2 - 50 - distanceToCenter, 0 ); + let random = Math.random() * variance / 2 * -1; + let point = { x: j+width/2-height/2, y: i + random }; + line.push( point ) + } + lines.push( line ); + } + + // Do the drawing + for ( let i = 0; i < lines.length; i++ ) { + + ctx.beginPath(); + ctx.moveTo( lines[i][0].x, lines[i][0].y ) + for ( var j = 0; j < lines[i].length - 2; j++ ) { + let xc = ( lines[i][j].x + lines[i][j + 1].x ) / 2; + let yc = ( lines[i][j].y + lines[i][j + 1].y ) / 2; + ctx.quadraticCurveTo( lines[i][j].x, lines[i][j].y, xc, yc ); + } + + ctx.quadraticCurveTo( lines[i][j].x, lines[i][j].y, lines[i][j + 1].x, lines[i][j + 1].y ); + ctx.fill(); + + ctx.stroke(); + if ( options.animate ){ + encoder.addFrame( ctx ); + } + } + + if ( options.animate ){ + encoder.setDelay( 2000 ); + encoder.addFrame( ctx ); + encoder.finish(); + if ( cb ){ + cb( null, fileUrlGIF ); + + } + } + else{ + if ( options.save ){ + const out = fs.createWriteStream( filePathPNG ), + stream = canvas.createPNGStream(); + + stream.pipe( out ); + + out.on( 'finish', function(){ + if ( cb ){ + cb( null, fileUrlPNG ); + } + } ); + } else { + cb( null, canvas.toBuffer().toString( 'base64' ) ); + } + } +} diff --git a/generators/triangular-mesh.js b/generators/triangular-mesh.js deleted file mode 100644 index 98875dc..0000000 --- a/generators/triangular-mesh.js +++ /dev/null @@ -1,123 +0,0 @@ -var fs = require('fs'), - crypto = require('crypto'), - Canvas = require('canvas'), - GIFEncoder = require('gifencoder'), - img_path = './.data/img', - helpers = require(__dirname + '/../helpers/general.js'); - -if (!fs.existsSync(img_path)){ - fs.mkdirSync(img_path); -} - -module.exports = function(options, cb) { - /* - Based on https://generativeartistry.com/tutorials/triangular-mesh/ - */ - console.log('making triangles...'); - var width = options.width || 1184, - height = options.height || 506, - colors = options.colors || ['000', 'fff'], - canvas = Canvas.createCanvas(width, height), - ctx = canvas.getContext('2d'); - - if (options.animate){ - var encoder = new GIFEncoder(width, height), - file_path = `${img_path}/${helpers.get_timestamp()}-${crypto.randomBytes(4).toString('hex')}`, - file_path_gif = `${file_path}.gif`; - - encoder.createReadStream().pipe(fs.createWriteStream(file_path_gif)); - - encoder.start(); - encoder.setRepeat(-1); // 0 for repeat, -1 for no-repeat - encoder.setDelay(100); // frame delay in milliseconds - encoder.setQuality(5); // image quality, 10 is default. - } - - ctx.lineWidth = 1; - ctx.fillStyle = `#${colors[0]}`; - ctx.strokeStyle = `#${colors[1]}`; - ctx.fillRect(0, 0, canvas.width, canvas.height); - - if (options.animate){ - encoder.addFrame(ctx); - } - - var line, dot, - odd = false, - lines = [], - gap = width / helpers.getRandomInt(5,12); - - for (var y = -2 * gap / 2; y <= 2 * height; y+= gap) { - odd = !odd - line = [] - for (var x = -2 * gap / 4; x <= 2 * width; x+= gap) { - line.push({ - x: x + (Math.random()*.8 - .4) * gap + (odd ? gap/2 : 0), - y: y + (Math.random()*.8 - .4) * gap, - }) - } - lines.push(line) - } - - function drawTriangle(pointA, pointB, pointC) { - ctx.beginPath(); - ctx.moveTo(pointA.x, pointA.y); - ctx.lineTo(pointB.x, pointB.y); - ctx.lineTo(pointC.x, pointC.y); - ctx.lineTo(pointA.x, pointA.y); - ctx.closePath(); - ctx.fillStyle = '#' + helpers.randomFromArray(options.colors); - ctx.fill(); - ctx.stroke(); - } - - var dotLine; - odd = true; - - for (var y = 0; y < lines.length - 1; y++) { - odd = !odd - dotLine = [] - for (var i = 0; i < lines[y].length; i++) { - dotLine.push(odd ? lines[y][i] : lines[y+1][i]) - dotLine.push(odd ? lines[y+1][i] : lines[y][i]) - } - for (var i = 0; i < dotLine.length - 2; i++) { - drawTriangle(dotLine[i], dotLine[i+1], dotLine[i+2]) - if (options.animate){ - encoder.addFrame(ctx); - } - } - } - - if (options.animate){ - encoder.setDelay(2000); - encoder.addFrame(ctx); - encoder.finish(); - helpers.load_image(`https://${process.env.PROJECT_DOMAIN}.glitch.me/gif`, - function(err, img_data_gif){ - if (cb){ - cb(null, { - path: file_path_gif.replace('./.data/', ''), - data: img_data_gif - }); - } - }); - } - else{ - var file_path = `${img_path}/${helpers.getTimestamp()}-${crypto.randomBytes(4).toString('hex')}`, - file_path_png = `${file_path}.png`, - out = fs.createWriteStream(file_path_png), - stream = canvas.createPNGStream(); - - stream.pipe(out); - - out.on('finish', function(){ - if (cb){ - cb(null, { - path: file_path_png.replace('./.data/', ''), - data: canvas.toBuffer().toString('base64') - }); - } - }); - } -} \ No newline at end of file diff --git a/helpers/colorbrewer.js b/helpers/colorbrewer.js new file mode 100644 index 0000000..7bb0139 --- /dev/null +++ b/helpers/colorbrewer.js @@ -0,0 +1,72 @@ +module.exports = [ + //Green to yellow + ["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"].reverse(), + //Blue-green-yellow + ["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"].reverse(), + //Blue to green + ["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"].reverse(), + //Green to blue + ["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"].reverse(), + //Green-blue-purple + ["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"].reverse(), + //Blue to purple + ["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"].reverse(), + //Purple to blue + ["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"].reverse(), + //Purple to red + ["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"].reverse(), + //Red to purple + ["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"].reverse(), + //Red to orange + ["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"].reverse(), + //Red-orange-yellow + ["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"].reverse(), + //Brown-orange-yellow + ["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"].reverse(), + //Purples + ["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"].reverse(), + //Blues + ["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"].reverse(), + //Greens + ["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"].reverse(), + //Oranges + ["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"].reverse(), + //Reds + ["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"].reverse(), + //Grays + ["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"].reverse(), + //Purple to orange + ["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"].reverse(), + //Green to brown + ["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"].reverse(), + //Purple to green + ["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"].reverse(), + //Purple to light green + ["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"].reverse(), + //Blue to red + ["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"].reverse(), + //Gray to red + ["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"].reverse(), + //Blue-yellow-red + ["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"].reverse(), + //Spectral + ["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"].reverse(), + //Green-yellow-red + ["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"].reverse(), + //Accent + ["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"].reverse(), + //Dark + ["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"].reverse(), + //Paired + ["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"].reverse(), + //Pastel 1 + ["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"].reverse(), + //Pastel 2 + ["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"].reverse(), + //Set 1 + ["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"].reverse(), + //Set 2 + ["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"].reverse(), + //Set 3 + ["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"].reverse() +]; \ No newline at end of file diff --git a/server.js b/server.js index 1cb37cf..20a659c 100644 --- a/server.js +++ b/server.js @@ -2,6 +2,13 @@ if ( !process.env.PROJECT_NAME || !process.env.PROJECT_ID ){ require( 'dotenv' ).config(); } +const fs = require('fs'), + imgPath = './.data/img'; + +if ( !fs.existsSync( imgPath ) ){ + fs.mkdirSync( imgPath ); +} + const app = require(__dirname + "/app.js"), db = require(__dirname + "/helpers/db.js"), bot = require(__dirname + "/bot/bot.js"), @@ -17,9 +24,9 @@ db.init(); // db.dropTable( 'Followers' ); // db.dropTable( 'Events' ); -// db.getFollowers( function( err, data ){ -// console.log( 'Followers:', data ); -// } ); +db.getFollowers( function( err, data ){ + console.log( 'Followers:', data ); +} ); // db.getPosts( function( err, data ){ // console.log( 'Posts:', data ); @@ -29,7 +36,7 @@ db.init(); // console.log( 'Events:', data ); // } ); -bot.script(); +// bot.script(); /* DEBUGGING END */ /*********************************************/ diff --git a/views/home.handlebars b/views/home.handlebars index 2f09cf3..f91e640 100644 --- a/views/home.handlebars +++ b/views/home.handlebars @@ -11,10 +11,12 @@ {{/if}} {{#equals this.type "Note"}} -
- -

{{{this.content}}}

-
+ {{#if this.content}} +
+ +

{{{this.content}}}

+
+ {{/if}} {{/equals}} {{/each}} {{#if has_posts}} - {{#if is_admin}}
diff --git a/views/post.handlebars b/views/post.handlebars index a7c13f6..792bf39 100644 --- a/views/post.handlebars +++ b/views/post.handlebars @@ -9,8 +9,10 @@ {{/if}} {{#each post.attachment}} -

-

{{this.content}}

+

{{this.content}}

+ {{#if this.content}} + + {{/if}} {{/each}}
{{/equals}}