diff --git a/chara.png b/chara.png new file mode 100644 index 0000000..ec001c2 Binary files /dev/null and b/chara.png differ diff --git a/cj/1/alchemist.png b/cj/1/alchemist.png new file mode 100644 index 0000000..1c2f9cc Binary files /dev/null and b/cj/1/alchemist.png differ diff --git a/cj/1/arcanist.png b/cj/1/arcanist.png new file mode 100644 index 0000000..1c9e9a0 Binary files /dev/null and b/cj/1/arcanist.png differ diff --git a/cj/1/archer.png b/cj/1/archer.png new file mode 100644 index 0000000..be2a860 Binary files /dev/null and b/cj/1/archer.png differ diff --git a/cj/1/armorer.png b/cj/1/armorer.png new file mode 100644 index 0000000..451ea5c Binary files /dev/null and b/cj/1/armorer.png differ diff --git a/cj/1/astrologian.png b/cj/1/astrologian.png new file mode 100644 index 0000000..f639782 Binary files /dev/null and b/cj/1/astrologian.png differ diff --git a/cj/1/bard.png b/cj/1/bard.png new file mode 100644 index 0000000..fd5a952 Binary files /dev/null and b/cj/1/bard.png differ diff --git a/cj/1/blackmage.png b/cj/1/blackmage.png new file mode 100644 index 0000000..1774842 Binary files /dev/null and b/cj/1/blackmage.png differ diff --git a/cj/1/blacksmith.png b/cj/1/blacksmith.png new file mode 100644 index 0000000..6a5cefa Binary files /dev/null and b/cj/1/blacksmith.png differ diff --git a/cj/1/bluemage.png b/cj/1/bluemage.png new file mode 100644 index 0000000..8feadf3 Binary files /dev/null and b/cj/1/bluemage.png differ diff --git a/cj/1/botanist.png b/cj/1/botanist.png new file mode 100644 index 0000000..023b75f Binary files /dev/null and b/cj/1/botanist.png differ diff --git a/cj/1/carpenter.png b/cj/1/carpenter.png new file mode 100644 index 0000000..4e459bc Binary files /dev/null and b/cj/1/carpenter.png differ diff --git a/cj/1/conjurer.png b/cj/1/conjurer.png new file mode 100644 index 0000000..8b7bc3d Binary files /dev/null and b/cj/1/conjurer.png differ diff --git a/cj/1/culinarian.png b/cj/1/culinarian.png new file mode 100644 index 0000000..4aeef51 Binary files /dev/null and b/cj/1/culinarian.png differ diff --git a/cj/1/dancer.png b/cj/1/dancer.png new file mode 100644 index 0000000..29f1e20 Binary files /dev/null and b/cj/1/dancer.png differ diff --git a/cj/1/darkknight.png b/cj/1/darkknight.png new file mode 100644 index 0000000..4aa7220 Binary files /dev/null and b/cj/1/darkknight.png differ diff --git a/cj/1/dragoon.png b/cj/1/dragoon.png new file mode 100644 index 0000000..9d826b9 Binary files /dev/null and b/cj/1/dragoon.png differ diff --git a/cj/1/fisher.png b/cj/1/fisher.png new file mode 100644 index 0000000..70ad8a5 Binary files /dev/null and b/cj/1/fisher.png differ diff --git a/cj/1/gladiator.png b/cj/1/gladiator.png new file mode 100644 index 0000000..1daa67f Binary files /dev/null and b/cj/1/gladiator.png differ diff --git a/cj/1/goldsmith.png b/cj/1/goldsmith.png new file mode 100644 index 0000000..96afc1b Binary files /dev/null and b/cj/1/goldsmith.png differ diff --git a/cj/1/gunbreaker.png b/cj/1/gunbreaker.png new file mode 100644 index 0000000..022e9c3 Binary files /dev/null and b/cj/1/gunbreaker.png differ diff --git a/cj/1/lancer.png b/cj/1/lancer.png new file mode 100644 index 0000000..a331f3f Binary files /dev/null and b/cj/1/lancer.png differ diff --git a/cj/1/leatherworker.png b/cj/1/leatherworker.png new file mode 100644 index 0000000..507f98b Binary files /dev/null and b/cj/1/leatherworker.png differ diff --git a/cj/1/machinist.png b/cj/1/machinist.png new file mode 100644 index 0000000..96b5331 Binary files /dev/null and b/cj/1/machinist.png differ diff --git a/cj/1/marauder.png b/cj/1/marauder.png new file mode 100644 index 0000000..6f6c546 Binary files /dev/null and b/cj/1/marauder.png differ diff --git a/cj/1/miner.png b/cj/1/miner.png new file mode 100644 index 0000000..c2e823a Binary files /dev/null and b/cj/1/miner.png differ diff --git a/cj/1/monk.png b/cj/1/monk.png new file mode 100644 index 0000000..21f33b3 Binary files /dev/null and b/cj/1/monk.png differ diff --git a/cj/1/ninja.png b/cj/1/ninja.png new file mode 100644 index 0000000..7437214 Binary files /dev/null and b/cj/1/ninja.png differ diff --git a/cj/1/paladin.png b/cj/1/paladin.png new file mode 100644 index 0000000..46c4906 Binary files /dev/null and b/cj/1/paladin.png differ diff --git a/cj/1/pugilist.png b/cj/1/pugilist.png new file mode 100644 index 0000000..52b25a2 Binary files /dev/null and b/cj/1/pugilist.png differ diff --git a/cj/1/redmage.png b/cj/1/redmage.png new file mode 100644 index 0000000..3d23aae Binary files /dev/null and b/cj/1/redmage.png differ diff --git a/cj/1/rogue.png b/cj/1/rogue.png new file mode 100644 index 0000000..a3979b8 Binary files /dev/null and b/cj/1/rogue.png differ diff --git a/cj/1/samurai.png b/cj/1/samurai.png new file mode 100644 index 0000000..9b66bfc Binary files /dev/null and b/cj/1/samurai.png differ diff --git a/cj/1/scholar.png b/cj/1/scholar.png new file mode 100644 index 0000000..9eb4bc6 Binary files /dev/null and b/cj/1/scholar.png differ diff --git a/cj/1/summoner.png b/cj/1/summoner.png new file mode 100644 index 0000000..29720a1 Binary files /dev/null and b/cj/1/summoner.png differ diff --git a/cj/1/thaumaturge.png b/cj/1/thaumaturge.png new file mode 100644 index 0000000..a9fadec Binary files /dev/null and b/cj/1/thaumaturge.png differ diff --git a/cj/1/warrior.png b/cj/1/warrior.png new file mode 100644 index 0000000..ea6b984 Binary files /dev/null and b/cj/1/warrior.png differ diff --git a/cj/1/weaver.png b/cj/1/weaver.png new file mode 100644 index 0000000..c7ce479 Binary files /dev/null and b/cj/1/weaver.png differ diff --git a/cj/1/whitemage.png b/cj/1/whitemage.png new file mode 100644 index 0000000..0fa86b9 Binary files /dev/null and b/cj/1/whitemage.png differ diff --git a/index.js b/index.js new file mode 100644 index 0000000..3bd69f9 --- /dev/null +++ b/index.js @@ -0,0 +1,238 @@ +const fetch = require("node-fetch"); +const fs = require("fs"); +const { createCanvas, loadImage } = require("canvas"); +const args = process.argv.slice(2); + +const canvas = createCanvas(900, 600); +const ctx = canvas.getContext("2d"); + +const primary = "rgba(178, 214, 249, 1)"; +const white = "rgba(255, 255, 255,1)"; +const black = "rgba(0,0,0,0.5)"; +const small = "18px Sans"; +const med = "30px Sans"; +const large = "40px Sans"; + +let charaID = "13821878"; + +function createCard(charaID, callback) { + let chara = ""; + fetch(`https://xivapi.com/character/${charaID}?extended=1&data=FC`) + .then((response) => response.json()) + .then((data) => { + ctx.clearRect(0, 0, 900, 600); + loadImage("./chara.png").then((image) => { + ctx.drawImage(image, 0, 0, 900, 600); + }); + loadImage(data.Character.Portrait).then((image) => { + ctx.drawImage(image, 0, 0, 441, 600); + ctx.strokeStyle = white; + ctx.fillStyle = black; + ctx.beginPath(); + ctx.fillRect(464, 7, 400, 100); + ctx.fillRect(464, 120, 400, 50); + ctx.fillRect(464, 185, 400, 205); + ctx.fillRect(464, 405, 400, 175); + ctx.stroke(); + ctx.textAlign = "center"; + ctx.font = med; + ctx.fillStyle = primary; + ctx.fillText(data.Character.Title.Name, 665, 45); + ctx.font = med; + ctx.fillText(`${data.Character.Server} (${data.Character.DC})`, 665, 155); + // Race, Clan, Guardian, GC, FC Titles + ctx.font = small; + ctx.textAlign = "left"; + ctx.fillText("Race & Clan", 480, 205); + ctx.fillText("Guardian", 480, 255); + if (data.Character.GrandCompany.Company != null) { + ctx.fillText("Grand Company", 480, 305); + } + if (data.Character.FreeCompanyName != null) { + ctx.fillText("Free Company", 480, 355); + } + ctx.fillStyle = white; + ctx.font = large; + ctx.textAlign = "center"; + // Chara Name + if (data.Character.Title.Name == null || data.Character.Title.Name == "") { + ctx.fillText(data.Character.Name, 665, 70); + } else { + ctx.fillText(data.Character.Name, 665, 90); + } + // Race, Clan, Guardian, GC, FC Info + ctx.font = "25px Sans"; + ctx.textAlign = "left"; + ctx.fillText(`${data.Character.Race.Name}, ${data.Character.Tribe.Name}`, 480, 230); + ctx.fillText(data.Character.GuardianDeity.Name, 480, 280); + if (data.Character.GrandCompany.Company != null) { + ctx.fillText(data.Character.GrandCompany.Company.Name, 480, 330); + } + if (data.Character.FreeCompanyName != null) { + ctx.fillText(data.Character.FreeCompanyName, 480, 380); + } + + // Why are there so many fucking jobs in this game? + // Crafting + ctx.font = "18px Sans"; + loadImage("./cj/1/alchemist.png").then((image) => { + ctx.drawImage(image, 480, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[24].Level, 486, 565); + + loadImage("./cj/1/armorer.png").then((image) => { + ctx.drawImage(image, 510, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[20].Level, 516, 565); + + loadImage("./cj/1/blacksmith.png").then((image) => { + ctx.drawImage(image, 540, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[19].Level, 546, 565); + + loadImage("./cj/1/carpenter.png").then((image) => { + ctx.drawImage(image, 570, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[18].Level, 576, 565); + + loadImage("./cj/1/culinarian.png").then((image) => { + ctx.drawImage(image, 600, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[25].Level, 606, 565); + + loadImage("./cj/1/goldsmith.png").then((image) => { + ctx.drawImage(image, 630, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[21].Level, 636, 565); + + loadImage("./cj/1/leatherworker.png").then((image) => { + ctx.drawImage(image, 660, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[22].Level, 666, 565); + + loadImage("./cj/1/weaver.png").then((image) => { + ctx.drawImage(image, 690, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[23].Level, 696, 565); + + // Gathering + loadImage("./cj/1/botanist.png").then((image) => { + ctx.drawImage(image, 750, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[27].Level, 756, 565); + + loadImage("./cj/1/fisher.png").then((image) => { + ctx.drawImage(image, 780, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[28].Level, 786, 565); + + loadImage("./cj/1/miner.png").then((image) => { + ctx.drawImage(image, 810, 520, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[26].Level, 816, 565); + + // Tanks + loadImage("./cj/1/paladin.png").then((image) => { + ctx.drawImage(image, 480, 415, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[0].Level, 486, 460); + + loadImage("./cj/1/warrior.png").then((image) => { + ctx.drawImage(image, 510, 415, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[1].Level, 516, 460); + + loadImage("./cj/1/darkknight.png").then((image) => { + ctx.drawImage(image, 540, 415, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[2].Level, 546, 460); + + loadImage("./cj/1/gunbreaker.png").then((image) => { + ctx.drawImage(image, 570, 415, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[3].Level, 576, 460); + + // Healers + loadImage("./cj/1/whitemage.png").then((image) => { + ctx.drawImage(image, 630, 415, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[8].Level, 636, 460); + + loadImage("./cj/1/scholar.png").then((image) => { + ctx.drawImage(image, 660, 415, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[9].Level, 666, 460); + + loadImage("./cj/1/astrologian.png").then((image) => { + ctx.drawImage(image, 690, 415, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[10].Level, 696, 460); + + // DPS + // Ranged + loadImage("./cj/1/bard.png").then((image) => { + ctx.drawImage(image, 750, 415, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[11].Level, 756, 460); + + loadImage("./cj/1/machinist.png").then((image) => { + ctx.drawImage(image, 780, 415, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[12].Level, 786, 460); + + loadImage("./cj/1/dancer.png").then((image) => { + ctx.drawImage(image, 810, 415, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[13].Level, 816, 460); + + // Melee + loadImage("./cj/1/dragoon.png").then((image) => { + ctx.drawImage(image, 480, 465, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[5].Level, 486, 515); + + loadImage("./cj/1/monk.png").then((image) => { + ctx.drawImage(image, 510, 465, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[4].Level, 516, 515); + + loadImage("./cj/1/ninja.png").then((image) => { + ctx.drawImage(image, 540, 465, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[6].Level, 546, 515); + + loadImage("./cj/1/samurai.png").then((image) => { + ctx.drawImage(image, 570, 465, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[7].Level, 576, 515); + + // Caster + loadImage("./cj/1/blackmage.png").then((image) => { + ctx.drawImage(image, 630, 465, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[14].Level, 636, 515); + + loadImage("./cj/1/summoner.png").then((image) => { + ctx.drawImage(image, 660, 465, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[15].Level, 666, 515); + + loadImage("./cj/1/redmage.png").then((image) => { + ctx.drawImage(image, 690, 465, 30, 30); + }); + ctx.fillText(data.Character.ClassJobs[16].Level, 696, 515); + + // Limited + loadImage("./cj/1/bluemage.png").then((image) => { + ctx.drawImage(image, 780, 465, 33, 33); + }); + ctx.fillText(data.Character.ClassJobs[17].Level, 786, 515); + + const png = canvas.toDataURL(); + + callback(png); + }); + }); +} + +exports.createCard = createCard; diff --git a/package.json b/package.json new file mode 100644 index 0000000..858252c --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "shit", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "scripts": { + "start": "node index.js", + "dev": "nodemon index.js" + }, + "dependencies": { + "canvas": "^2.6.1", + "node-fetch": "^2.6.1", + "nodemon": "^2.0.7" + } +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..dbd3ad1 --- /dev/null +++ b/readme.md @@ -0,0 +1,2 @@ +# XIV Character Cards + diff --git a/test.js b/test.js new file mode 100644 index 0000000..14a6863 --- /dev/null +++ b/test.js @@ -0,0 +1,18 @@ +const fs = require("fs"); +const createCard = require("./index").createCard; + +createCard("9575452", (png) => { + const data = png.replace(/^data:image\/\w+;base64,/, ""); + const buf = Buffer.from(data, "base64"); + fs.writeFile('test.png', buf, (err) => { + console.log(err) + }) + }); + +createCard("13821878", (png) => { + const data = png.replace(/^data:image\/\w+;base64,/, ""); + const buf = Buffer.from(data, "base64"); + fs.writeFile('image.png', buf, (err) => { + console.log(err) + }) +});