diff --git a/TurtleTemplate.png b/TurtleTemplate.png new file mode 100644 index 0000000..ba669e4 Binary files /dev/null and b/TurtleTemplate.png differ diff --git a/index.js b/index.js index b917f5f..7112b1c 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,7 @@ var request = require("request"); var Discord = require('discord.js'); const Canvas = require("canvas"); -const Image = Canvas.Image; +const Image = Canvas.Image; const twemoji = require("./twemoji"); @@ -12,100 +12,119 @@ var config = require("./config"); var cache = {}; -const beeTemplate = new Image(); -beeTemplate.src = "./BeeTemplate.png"; +templates = { + bee: { + template: "./BeeTemplate.png", + leftOffset: 475, + widthTarget: 600, + bottomTarget: 530 + }, + turtle: { + template: "./TurtleTemplate.png", + leftOffset: 210, + widthTarget: 150, + bottomTarget: 150 + } +} + +for(templateName in templates) { + const data = templates[templateName]; + data.image = new Image(); + data.image.src = data.template; +} -function bee(url, size) { - return new Promise((resolve,reject)=>{ - console.log("Getting "+url); - if(url) { - request.get({url:url, encoding: null}, function(e, r, data) { - if(e) { - reject({status: (r && r.statusCode || 500), error: e}); - return; +function render(template, url, size) { + return new Promise((resolve, reject) => { + console.log("Getting " + url); + if (url) { + request.get({ url: url, encoding: null }, function (e, r, data) { + if (e) { + reject({ status: (r && r.statusCode || 500), error: e }); + return; } var img = new Image(); img.src = data; console.log("image loaded"); var width = img.width; var height = img.height; - if(size && size.height) { + if (size && size.height) { height = size.height; - if(!size.width) width = width * size.height / img.height; + if (!size.width) width = width * size.height / img.height; } - if(size && size.width) { + if (size && size.width) { width = size.width; - if(!size.height) height = height * size.width / img.width; + if (!size.height) height = height * size.width / img.width; } - const leftOffset = 475.0; // relative to bee template width - const widthTarget = 600.0; // relative to bee template width - const bottomTarget = 530; // relative to bee template height + const templateScale = width / template.widthTarget; // scale the template to fit the image - const beeScale = width / widthTarget; // scale the bee to fit the image - - const resultingWidth = beeTemplate.width * beeScale; - let resultingHeight = beeTemplate.height * beeScale; + let resultingWidth = template.image.width * templateScale; + let resultingHeight = template.image.height * templateScale; - let imgTop = bottomTarget * beeScale - height; // naive top center position + let imgTop = template.bottomTarget * templateScale - height; // naive top center position - if(imgTop < 0) { + if (imgTop < 0) { resultingHeight -= imgTop; imgTop = 0; } const resultingImgTop = imgTop; - const resultingImgLeft = leftOffset * beeScale - width / 2.0; + const resultingImgLeft = template.leftOffset * templateScale - width / 2.0; - const resultingBeeTop = resultingHeight - beeTemplate.height * beeScale; - const resultingBeeLeft = 0.0; + if(resultingImgLeft + width > resultingWidth) { + resultingWidth = resultingImgLeft + width; + } + + const resultingTemplateTop = resultingHeight - template.image.height * templateScale; + const resultingTemplateLeft = 0.0; var canvas = new Canvas(resultingWidth, resultingHeight); var ctx = canvas.getContext("2d"); - console.log("Drawing first image") + console.log("Drawing template") try { - ctx.drawImage(beeTemplate, resultingBeeLeft, resultingBeeTop, resultingWidth, beeTemplate.height * beeScale); + ctx.drawImage(template.image, resultingTemplateLeft, resultingTemplateTop, template.image.width * templateScale, template.image.height * templateScale); console.log("Drawing done.") - } catch(err) { - reject({status: 400, error: "Invalid template"}) + } catch (err) { + reject({ status: 400, error: "Invalid template" }) } - console.log("Drawing second image") + console.log("Drawing image") try { ctx.drawImage(img, resultingImgLeft, resultingImgTop, width, height); console.log("Drawing done.") - } catch(err) { + } catch (err) { console.error(err); - reject({status: 400, error: "Invalid image"}) + reject({ status: 400, error: "Invalid image" }) } - + // return the image and cache it resolve(canvas); }); } else { - reject({status: 400, error: "No url specified"}); + reject({ status: 400, error: "No url specified" }); } }); } const circleScale = 0.4; const lineWidthScale = 0.2; -const lowerRightFactor = 0.5 + 0.7071*circleScale; // %-ual location of the lower right end of the strikethrough line -const upperLeftFactor = 0.5 - 0.7071*circleScale; // %-ual location of the upper left end of the strikethrough line +const lowerRightFactor = 0.5 + 0.7071 * circleScale; // %-ual location of the lower right end of the strikethrough line +const upperLeftFactor = 0.5 - 0.7071 * circleScale; // %-ual location of the upper left end of the strikethrough line -app.get("/bee/", function(req, res) { - bee(req.query.url).then((canvas)=>{ +app.get("/:templateName/", function (req, res) { + if(!templates[req.params.templateName]) return res.status(404).end(); + render(templates[req.params.templateName], req.query.url).then((canvas) => { console.log(canvas) res.setHeader('Content-Type', 'image/png'); canvas.pngStream().pipe(res); - }).catch((err)=>{ + }).catch((err) => { res.status(err.status).end(err.error); }) }); app.listen(3002, function () { - console.log('Beebot app listening on port 3002!') + console.log('Beebot app listening on port 3002!') }) @@ -114,26 +133,26 @@ app.listen(3002, function () { var client = new Discord.Client({ - autoReconnect: true + autoReconnect: true }); // manage roles permission is required const invitelink = 'https://discordapp.com/oauth2/authorize?client_id=' - + config.discord.client_id + '&scope=bot&permissions=0'; + + config.discord.client_id + '&scope=bot&permissions=0'; const authlink = 'https://discordapp.com/oauth2/authorize?client_id=' - + config.discord.client_id + '&scope=email'; -console.log("Bot invite link: "+invitelink); + + config.discord.client_id + '&scope=email'; +console.log("Bot invite link: " + invitelink); client.login(config.discord.token).catch(function (error) { - if (error) { - console.error("Couldn't login: ", error); - process.exit(15); - } + if (error) { + console.error("Couldn't login: ", error); + process.exit(15); + } }); function findEmoji(str) { const discordEmote = /<:(\w+):(\d+)>/g.exec(str) - if(discordEmote) { + if (discordEmote) { return { name: discordEmote[1], id: discordEmote[2], @@ -142,10 +161,10 @@ function findEmoji(str) { } let unicodeEmoji; - twemoji.parse(str, (name, emoji) =>{ - if(unicodeEmoji) return false; + twemoji.parse(str, (name, emoji) => { + if (unicodeEmoji) return false; unicodeEmoji = { - name, + name, id: name, url: emoji.base + emoji.size + "/" + name + emoji.ext } @@ -156,16 +175,17 @@ function findEmoji(str) { client.on('message', function (message) { console.log(message.cleanContent); - if (message.cleanContent.startsWith("/bee")) { - // get emoji from message - const emoji = findEmoji(message.cleanContent); - if(emoji) bee(emoji.url).then(canvas => { - var messageOptions = { - files: [ - {attachment: canvas.toBuffer(), name: emoji.name.toUpperCase()+"DETECTED.png"} - ] - } - message.channel.send("", messageOptions); - }); - } + const commandParsed = /^\/(\w+)\b/.exec(message.cleanContent); + if (commandParsed && templates[commandParsed[1]]) { + // get emoji from message + const emoji = findEmoji(message.cleanContent); + if (emoji) render(templates[commandParsed[1]], emoji.url).then(canvas => { + var messageOptions = { + files: [ + { attachment: canvas.toBuffer(), name: emoji.name + commandParsed[1] + ".png" } + ] + } + message.channel.send("", messageOptions); + }); + } }); \ No newline at end of file