diff --git a/Xiao.js b/Xiao.js index 7f429c07..ac699d3b 100644 --- a/Xiao.js +++ b/Xiao.js @@ -57,6 +57,9 @@ client.registry client.on('ready', async () => { client.logger.info(`[READY] Logged in as ${client.user.tag}! ID: ${client.user.id}`); + // Register all canvas fonts + await client.registerFontsIn(path.join(__dirname, 'assets', 'fonts')); + // Set up existing timers await client.timers.fetchAll(); diff --git a/package.json b/package.json index 8c0dc4ce..a19d6593 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "eslint": "^7.19.0", "expr-eval": "^2.0.2", "fen-validator": "^1.4.1", + "font-finder": "^1.1.0", "gifencoder": "^2.0.1", "gm": "^1.23.1", "html-entities": "^2.1.0", diff --git a/structures/Client.js b/structures/Client.js index 9a1cafb5..e6a794ad 100644 --- a/structures/Client.js +++ b/structures/Client.js @@ -2,9 +2,11 @@ const { CommandoClient } = require('discord.js-commando'); const { WebhookClient } = require('discord.js'); const Collection = require('@discordjs/collection'); const winston = require('winston'); +const fontFinder = require('font-finder'); const fs = require('fs'); const path = require('path'); const Redis = require('./Redis'); +const Font = require('./Font'); const PhoneManager = require('./phone/PhoneManager'); const TimerManager = require('./remind/TimerManager'); const PokemonStore = require('./pokemon/PokemonStore'); @@ -33,6 +35,7 @@ module.exports = class XiaoClient extends CommandoClient { winston.format.printf(log => `[${log.timestamp}] [${log.level.toUpperCase()}]: ${log.message}`) ) }); + this.fonts = new Map(); this.redis = Redis ? Redis.db : null; this.webhook = new WebhookClient(XIAO_WEBHOOK_ID, XIAO_WEBHOOK_TOKEN, { disableMentions: 'everyone' }); this.timers = new TimerManager(this); @@ -51,6 +54,17 @@ module.exports = class XiaoClient extends CommandoClient { this.leaveMessages = leaveMsgs; } + async registerFontsIn(path) { + const files = fs.readdirSync(path); + for (const file of files) { + const metadata = await fontFinder.get(path.join(path, file)); + const font = new Font(path.join(path, file), file, metadata); + this.fonts.set(file, font); + font.register(); + } + return this.fonts; + } + importBlacklist() { const read = fs.readFileSync(path.join(__dirname, '..', 'blacklist.json'), { encoding: 'utf8' }); const file = JSON.parse(read); diff --git a/structures/Font.js b/structures/Font.js new file mode 100644 index 00000000..a95e2da0 --- /dev/null +++ b/structures/Font.js @@ -0,0 +1,34 @@ +const { registerFont } = require('canvas'); +const weights = { + 100: 'thin', + 200: 'extraLight', + 300: 'light', + 400: 'normal', + 500: 'medium', + 600: 'semiBold', + 700: 'bold', + 800: 'extraBold', + 900: 'heavy', + 950: 'extraBlack' +}; + +module.exports = class Font { + constructor(path, filename, metadata) { + this.path = path; + this.name = metadata.name || filename; + this.style = metadata.style === 'regular' ? 'normal' : metadata.style || 'normal'; + this.weight = weights[metadata.weight] || metadata.weight || 'normal'; + this.type = metadata.type; + this.registered = false; + } + + register() { + if (this.registered) return null; + this.registered = true; + return registerFont(this.path, { family: this.name, style: this.style, weight: this.weight }); + } + + toCanvasString(size) { + return `${this.style} ${this.weight} ${size}px ${this.name}`; + } +};