X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=index.js;h=07da00a59a99919049ac8d9c6319e2a7a0a42c83;hb=c7399ddc7ac3efd6797c3011959f2ac9d3f6e966;hp=249537fd3414cd2541b16513901ab6eaeb68359a;hpb=1e105bc031bb09cc823f656a5e0c1601f18a1d4f;p=zombocom-ai diff --git a/index.js b/index.js index 249537f..07da00a 100644 --- a/index.js +++ b/index.js @@ -1,28 +1,55 @@ const fs = require('fs'); +const util = require('util'); +const execFile = util.promisify(require('child_process').execFile); + const express = require('express'); const app = express(); +const session = require('express-session'); +const FileStore = require('session-file-store')(session); const http = require('http'); const server = http.createServer(app); const { Server } = require("socket.io"); const io = new Server(server); const port = 2122; +const python_path = '/usr/bin/python3' +const generate_image_script = '/home/cworth/src/zombocom-ai/generate-image.py' const state_file = 'zombocom-state.json' -var comments; +var state; + +if (!process.env.ZOMBOCOM_SESSION_SECRET) { + console.log("Error: Environment variable ZOMBOCOM_SESSION_SECRET not set."); + console.log("Please set it to a random, but persistent, value.") + process.exit(); +} + +const session_middleware = session( + {store: new FileStore, + secret: process.env.ZOMBOCOM_SESSION_SECRET, + resave: false, + saveUninitialized: true + }); + +app.use(session_middleware); + +// convert a connect middleware to a Socket.IO middleware +const wrap = middleware => (socket, next) => middleware(socket.request, {}, next); + +io.use(wrap(session_middleware)); // Load comments at server startup fs.readFile(state_file, (err, data) => { if (err) - comments = []; + state = { images: [] }; else - comments = JSON.parse(data); + state = JSON.parse(data); }); // Save comments when server is shutting down function cleanup() { - fs.writeFileSync('zombocom-state.json', JSON.stringify(comments), (error) => { + fs.writeFileSync('zombocom-state.json', JSON.stringify(state), (error) => { if (error) throw error; }) @@ -43,20 +70,78 @@ app.get('/index.html', (req, res) => { io.on('connection', (socket) => { - // Replay old comments to a newly-joining client - comments.forEach((comment) => { - socket.emit('comment', comment) + // First things first, tell the client their name (if any) + if (socket.request.session.name) { + socket.emit('inform-name', socket.request.session.name); + } + + // Replay old comments and images to a newly-joining client + socket.emit('reset'); + state.images.forEach((image) => { + socket.emit('image', image) + }); + + socket.on('set-name', (name) => { + console.log("Received set-name event: " + name); + socket.request.session.name = name; + socket.request.session.save(); + // Complete the round trip to the client + socket.emit('inform-name', socket.request.session.name); }); // When any client comments, send that to all clients (including sender) socket.on('comment', (comment) => { + const images = state.images; + + // Send comment to clients after adding commenter's name + comment.name = socket.request.session.name; io.emit('comment', comment); - comments.push(comment); + + const index = images.findIndex(image => image.id == comment.image_id); + + // Before adding the comment to server's state, drop the image_id + delete comment.image_id; + + // Now add the comment to the image, remove the image from the + // images array and then add it back at the end, (so it appears + // as the most-recently-modified image for any new clients) + const image = images[index]; + image.comments.push(comment); + images.splice(index, 1); + images.push(image); }); // Generate an image when requested socket.on('generate', (request) => { - console.log(`Generating image with code=${request['code']} and prompt=${request['prompt']}`); + console.log(`Generating image for ${socket.request.session.name} with code=${request['code']} and prompt=${request['prompt']}`); + async function generate_image(code, prompt) { + var promise; + if (code) { + promise = execFile(python_path, [generate_image_script, `--seed=${code}`, prompt]) + } else { + promise = execFile(python_path, [generate_image_script, prompt]) + } + const child = promise.child; + child.stdout.on('data', (data) => { + const images = JSON.parse(data); + images.forEach((image) => { + image.id = state.images.length; + image.comments = []; + io.emit('image', image); + state.images.push(image); + }); + }); + child.stderr.on('data', (data) => { + console.log("Error occurred during generate-image: " + data); + }); + try { + const { stdout, stderr } = await promise; + } catch(e) { + console.error(e); + } + socket.emit('generation-done'); + } + generate_image(request['code'], request['prompt']); }); });