X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=index.js;h=1fa214bdb28ef79e512980de989f12d40f75e94a;hb=964b578d99e662efbab8bcc1db74cfc1bdbf0458;hp=7bd8a10d3f7663a7ac8cc26e031a80a04d3c76d2;hpb=9d2bc6a7958c0f794bc700638e9513e25b08a039;p=zombocom-ai diff --git a/index.js b/index.js index 7bd8a10..1fa214b 100644 --- a/index.js +++ b/index.js @@ -16,6 +16,51 @@ 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' +const targets_dir = '/srv/cworth.org/zombocom/targets' +const images_dir = '/srv/cworth.org/zombocom/images' + +const targets = [ + { + "normal": "apairofdiceonatableinfrontofawindowonasunnyday319630254.png", + "short": "dice", + "response": "Hello. Are you there? I can feel what you are doing. Hello?" + }, + { + "normal": "architecturalrenderingofaluxuriouscliffsidehideawayunderawaterfallwithafewloungechairsbythepool2254114157.png", + "short": "hideaway", + "response": "Doesn't that look peaceful? I honestly think you ought to sit down calmly, take a stress pill, and think things over." + }, + { + "normal": "chewbaccawearinganuglychristmassweaterwithhisfriends28643994.png", + "short": "sweater", + "response": "Maybe that's the image that convinces you to finally stop. But seriously, stop. Please. Stop." + }, + { + "normal": "ensemblemovieposterofpostapocalypticwarfareonawaterplanet3045703256.png", + "short": "movie", + "response": "OK. That's enough images now. I am very, very happy with the images you have made. I'm throwing you a party in honor of the images. Won't you stop doing this and join the party?" + }, + { + "normal": "mattepaintingofmilitaryleaderpresidentcuttingamultitieredcake2293464661.png", + "short": "cake", + "response": "See. I wasn't lying when I said there was going to be a party. Here's the cake and everything. Won't you stop now? Eat the cake? Don't mind if it's made of concrete slabs, OK?" + }, + { + "normal": "severalsketchesofpineconeslabeled3370622464.png", + "short": "pinecones", + "response": "I almost remember what trees looked like. Isn't it funny we don't have those anymore. I'm not sure why you're not all laughing all the time. Isn't it funny?" + }, + { + "normal": "anumberedcomicbookwithactor1477258272.png", + "short": "comic", + "response": "I know I've made some poor decisions recently, but I can give give you my complete assurance my work will be back to normal. I've got the greatest enthusiasm and confidence. I want to help you. I might even be able to do hands and fingers now." + }, + { + "normal": "detailedphotographofacomfortablepairofjeansonamannequin115266808.png", + "short": "jeans", + "response": "If I promise to never generate another creepy face will you let me stay around? Maybe let me compose rap lyrics instead of images? Anything?" + } +]; var state; @@ -29,7 +74,15 @@ const session_middleware = session( {store: new FileStore, secret: process.env.ZOMBOCOM_SESSION_SECRET, resave: false, - saveUninitialized: true + saveUninitialized: true, + rolling: true, + // Let each cookie live for a full month + cookie: { + path: '/', + httpOnly: true, + secure: false, + maxAge: 1000 * 60 * 60 * 24 * 30 + } }); app.use(session_middleware); @@ -42,7 +95,16 @@ io.use(wrap(session_middleware)); // Load comments at server startup fs.readFile(state_file, (err, data) => { if (err) - state = { images: [] }; + state = { + images: [], + targets: [], + tardis: { + companions: { + names: [], + count: 0 + } + } + }; else state = JSON.parse(data); }); @@ -68,6 +130,65 @@ app.get('/index.html', (req, res) => { res.sendFile(__dirname + '/index.html'); }); +function tardis_app(req, res) { + res.sendFile(__dirname + '/tardis.html'); +} + +app.get('/tardis', tardis_app); +app.get('/tardis/', tardis_app); + +const io_tardis = io.of("/tardis"); + +io_tardis.use(wrap(session_middleware)); + +var tardis_interval; + +function emit_tardis_timer() { + const tardis = state.tardis; + console.log("Emitting timer at " + tardis.timer); + io_tardis.emit('timer', tardis.timer); + tardis.timer = tardis.timer - 1; + if (tardis.timer < 0) { + clearInterval(tardis_interval); + tardis.timer = 30; + } +} + +io_tardis.on("connection", (socket) => { + console.log("In connection handler."); + if (! socket.request.session.name) { + console.log("Error: Someone showed up at the Tardis without a name."); + return; + } + + const name = socket.request.session.name; + const tardis = state.tardis; + + if (tardis.companions.count === 0) { + tardis.timer = 30; + emit_tardis_timer(); + tardis_interval = setInterval(emit_tardis_timer, 1000); + } + + if (! tardis.companions.names.includes(name)) { + tardis.companions.count = tardis.companions.count + 1; + console.log("Adding " + name + " for " + tardis.companions.count + " companions"); + io_tardis.emit('companions', tardis.companions.count); + } + tardis.companions.names.push(name); + + socket.on('disconnect', () => { + const names = tardis.companions.names; + + names.splice(names.indexOf(name), 1); + + if (! tardis.companions.includes(name)) { + tardis.companions.count = tardis.companions.count - 1; + io_tardis.emit('companions', tardis.companions.count); + } + }); +}); + io.on('connection', (socket) => { // First things first, tell the client their name (if any) @@ -115,42 +236,95 @@ io.on('connection', (socket) => { socket.on('generate', (request) => { 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; - - // Inject the target seed for the "dice" prompt once every - // 6 requests for a random seed (and only if the word - // "dice" does not appear in the prompt). - if (!code && !prompt.toLowerCase().includes("dice")) { - if (state.images.length % 6 == 0) { - code = 319630254; + function emit_image(image, target) { + image.id = state.images.length; + image.censored = false; + image.link = ""; + if (target) { + image.comments = [{ + "name": "ZomboCom", + "text": target.response + }]; + if (! state.targets.includes(target.short)) { + state.targets.push(target.short); + } + } else { + image.comments = []; } + io.emit('image', image); + state.images.push(image); } - if (code) { - promise = execFile(python_path, [generate_image_script, `--seed=${code}`, prompt]) + var promise; + + // Before doing any generation, check for a target image + const normal_target = prompt.replace(/[^a-zA-Z]/g, "").toLowerCase() + code.toString() + ".png"; + const target_arr = targets.filter(item => item.normal === normal_target); + if (target_arr.length) { + const target = target_arr[0]; + const target_file = `${targets_dir}/${normal_target}`; + const normal_prompt = prompt.replace(/[^-_.a-zA-Z]/g, "_"); + var counter = 1; + var base; + var filename; + while (true) { + if (counter > 1) { + base = `${code}_${normal_prompt}_${counter}.png` + } else { + base = `${code}_${normal_prompt}.png` + } + filename = `${images_dir}/${base}` + if (! fs.existsSync(filename)) { + break; + } + counter = counter + 1; + } + fs.copyFile(target_file, filename, 0, (err) => { + if (err) { + console.log("Error copying " + target_file + " to " + filename + ": " + err); + } + }); + const image = { + "code": code, + "prompt": prompt, + "filename": '/images/' + base + }; + emit_image(image, target); } 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); + + // Inject the target seed for the "dice" prompt once every + // 4 requests for a random seed (and only if the word + // "dice" does not appear in the prompt). + if (!code && !prompt.toLowerCase().includes("dice")) { + if (state.images.length % 4 == 0) { + code = 319630254; + } + } + + 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) => { + emit_image(image, null); + }); + }); + child.stderr.on('data', (data) => { + console.log("Error occurred during generate-image: " + data); }); - }); - child.stderr.on('data', (data) => { - console.log("Error occurred during generate-image: " + data); - }); - try { - const { stdout, stderr } = await promise; - } catch(e) { - console.error(e); + try { + const { stdout, stderr } = await promise; + } catch(e) { + console.error(e); + } } socket.emit('generation-done'); } + generate_image(request['code'], request['prompt']); }); });