diff --git a/assets/profile/profile.svg b/assets/profile/profile.svg index 58b2380..5c91cd3 100644 --- a/assets/profile/profile.svg +++ b/assets/profile/profile.svg @@ -1,8 +1,10 @@ - - - + + + + + @@ -25,11 +27,11 @@ - + - + - + @@ -45,9 +47,9 @@ - + - + @@ -65,7 +67,7 @@ - + {{USERNAME}} diff --git a/assets/profile/template.afdesign b/assets/profile/template.afdesign index a18a690..3584ed9 100644 Binary files a/assets/profile/template.afdesign and b/assets/profile/template.afdesign differ diff --git a/commands/profile.js b/commands/profile.js index 0179945..1d4a71b 100644 --- a/commands/profile.js +++ b/commands/profile.js @@ -1,6 +1,7 @@ const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require("discord.js"); const { Card, User, Character } = require("../models"); -const UserUtils = require("../util/users"); +const { UserUtils, Compositing, Rendering } = require("../util"); +const fs = require('fs'); const pageSize = 8; @@ -10,9 +11,26 @@ module.exports = { .setName("profile") .setDescription("View your profile"), async execute(interaction) { + await interaction.deferReply(); let user = await UserUtils.getUserByDiscordId(interaction.member.id); let profile = await user.getProfile(); - await interaction.reply(`json: ${JSON.stringify(profile)}`); + + let profileTemplate = fs.readFileSync('/app/assets/profile/profile.svg').toString(); + profileTemplate = profileTemplate.replace(/{{USERNAME}}/g, interaction.member.user.username); + profileTemplate = profileTemplate.replace(/{{HEADER_COLOR}}/g, '190,31,97'); + + let slots = ['slotOne', 'slotTwo', 'slotThree', 'slotFour']; + let renderedCards = []; + for (slot of slots) { + let card = await Card.findOne({ where: { id: profile[slot] }}); + if (card) { + let cardImage = await Rendering.renderCard(card); + renderedCards.push(cardImage); + } + } + + let profileImage = await Compositing.renderProfile(profile, profileTemplate, renderedCards); + await interaction.editReply({ files: [profileImage] }); } } \ No newline at end of file diff --git a/util/compositing.js b/util/compositing.js new file mode 100644 index 0000000..d929157 --- /dev/null +++ b/util/compositing.js @@ -0,0 +1,42 @@ +const { spawn } = require('child_process'); +const crypto = require('crypto'); +const fs = require('fs'); +const { Card } = require('../models'); + +//TODO: Handle missing images +module.exports = { + name: "Compositing", + renderProfile: async function(profile, svgTemplate, renderedCards) { + let hash = crypto.createHash('md5').update(JSON.stringify(profile)).digest('hex'); + + let outFile = `/app/assets/image_cache/profiles/${hash}.gif`; + console.log('Rendering profile to ' + outFile); + + //composite {overlay} {background} [{mask}] [-compose {method}] {result} + let args = ['svg:-', 'null:', + '\(', `${renderedCards[0]}`, '-coalesce', '\)', + '-geometry', '+25+85', '-compose', 'over', '-layers', 'composite', + 'null:', '\(', `${renderedCards[1]}`, '-coalesce', '-resize', '170x283', '\)', + '-geometry', '+350+300', '-compose', 'over', '-layers', 'composite', + 'null:', '\(', `${renderedCards[2]}`, '-coalesce', '-resize', '170x283', '\)', + '-geometry', '+535+300', '-compose', 'over', '-layers', 'composite', + 'null:', '\(', `${renderedCards[3]}`, '-coalesce', '-resize', '170x283', '\)', + '-geometry', '+720+300', '-compose', 'over', '-layers', 'composite', + '-layers', 'optimize', outFile]; + + console.log('GM Args: ' + args); + + const composite = spawn('convert', args); + composite.stdin.write(svgTemplate); + composite.stdin.end(); + + composite.stderr.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + const exitCode = await new Promise( (resolve, reject) => { + composite.on('close', resolve); + }) + + return outFile; + } +}