UNPKG

peechu

Version:

Peechu Music Card.

129 lines (108 loc) 6.03 kB
const canvas = require("@napi-rs/canvas"); const path = require('path'); const { colorFetch } = require("../functions/colorFetch"); canvas.GlobalFonts.registerFromPath(path.join(__dirname, '../node_modules/peechu/build/structures/font/circularstd-black.otf'), "circular-std"); canvas.GlobalFonts.registerFromPath(path.join(__dirname, '../node_modules/peechu/build/structures/font/notosans-jp-black.ttf'), "noto-sans-jp"); canvas.GlobalFonts.registerFromPath(path.join(__dirname, '../node_modules/peechu/build/structures/font/notosans-black.ttf'), "noto-sans"); canvas.GlobalFonts.registerFromPath(path.join(__dirname, '../node_modules/peechu/build/structures/font/notoemoji-bold.ttf'), "noto-emoji"); canvas.GlobalFonts.registerFromPath(path.join(__dirname, '../node_modules/peechu/build/structures/font/notosans-kr-black.ttf'), "noto-sans-kr"); canvas.GlobalFonts.registerFromPath(path.join(__dirname, '../node_modules/musicard-bun/build/structures/font/Chewy-Regular.ttf'), "chewy"); canvas.GlobalFonts.registerFromPath(path.join(__dirname, '../node_modules/musicard-bun/build/structures/font/Space.ttf'), "space"); const DEFAULT_THUMBNAIL = path.join(__dirname, '../assets/no_thumbnail.png'); const BACKGROUND_IMAGES_DIR = path.join(__dirname, '../assets/backgrounds'); const BACKGROUND_FILES = [ '1.png', '2.png', '3.png', '4.png', '5.png', '6.png', '7.png', '8.png', '9.png', '10.png', '11.png', '12.png', '13.png', '14.png', '15.png', '16.png', '17.png', '18.png', '19.png', '20.png', '21.png', ]; const ALLOWED_COLORS = ['#ebb866', '#ffc3bf', '#fcfcfc']; class peechu { constructor(options) { this.name = options?.name ?? null; this.author = options?.author ?? null; this.color = options?.color ?? null; this.theme = options?.theme ?? 'peechu'; this.brightness = options?.brightness ?? 0; this.thumbnail = options?.thumbnail ?? DEFAULT_THUMBNAIL; this.progress = options?.progress ?? 0; this.starttime = options?.startTime ?? '0:00'; this.endtime = options?.endTime ?? '0:00'; this.requester = options?.requester ?? null; } setName(name) { this.name = name; return this; } setAuthor(author) { this.author = author; return this; } setColor(color) { this.color = color; return this; } setTheme(theme) { this.theme = theme || 'peechu'; return this; } setBrightness(brightness) { this.brightness = brightness; return this; } setThumbnail(thumbnail) { this.thumbnail = thumbnail; return this; } setProgress(progress) { this.progress = progress; return this; } setStartTime(starttime) { this.starttime = starttime; return this; } setEndTime(endtime) { this.endtime = endtime; return this; } setRequester(requester) { this.requester = `${requester}`; return this; } async build() { if (!this.color) this.setColor('ff0000'); let validatedProgress = parseFloat(this.progress); if (Number.isNaN(validatedProgress) || validatedProgress < 0 || validatedProgress > 100) throw new Error('Invalid progress parameter, must be between 0 to 100'); validatedProgress = Math.max(2, Math.min(validatedProgress, 99)); const validatedColor = await colorFetch(this.color, parseInt(this.brightness), this.thumbnail); this.name = this.name?.length > 15 ? `${this.name.slice(0, 15)}...` : this.name; this.author = this.author?.length > 15 ? `${this.author.slice(0, 15)}` : this.author; this.requester = this.requester?.length > 12 ? `${this.requester.slice(0, 10)}...` : this.requester; if (this.theme === 'peechu') { const frame = canvas.createCanvas(800, 200); const ctx = frame.getContext("2d"); const backgroundFile = BACKGROUND_FILES[Math.floor(Math.random() * BACKGROUND_FILES.length)]; const backgroundPath = path.join(BACKGROUND_IMAGES_DIR, backgroundFile); const background = await canvas.loadImage(backgroundPath); ctx.drawImage(background, 0, 0, frame.width, frame.height); const thumbnailCanvas = canvas.createCanvas(800, 200); const thumbnailCtx = thumbnailCanvas.getContext('2d'); let thumbnailImage; try { thumbnailImage = await canvas.loadImage(this.thumbnail); } catch { thumbnailImage = await canvas.loadImage(DEFAULT_THUMBNAIL); } const thumbnailSize = Math.min(thumbnailImage.width, thumbnailImage.height); thumbnailCtx.drawImage(thumbnailImage, (thumbnailImage.width - thumbnailSize) / 2, (thumbnailImage.height - thumbnailSize) / 2, thumbnailSize, thumbnailSize, 0, 0, thumbnailCanvas.width, thumbnailCanvas.height); ctx.drawImage(thumbnailCanvas, 50, 40, 180, 130); ctx.strokeStyle = '#CF9FFF'; ctx.lineWidth = 5; ctx.strokeRect(50, 40, 180, 130); const randomColor = () => ALLOWED_COLORS[Math.floor(Math.random() * ALLOWED_COLORS.length)]; ctx.font = "bold 38px circular-std, noto-emoji, noto-sans-jp, noto-sans, noto-sans-kr"; ctx.fillStyle = randomColor(); ctx.fillText(this.name, 250, 100); ctx.font = "bold 22px circular-std, noto-emoji, noto-sans-jp, noto-sans, noto-sans-kr"; ctx.fillStyle = randomColor(); const authorTextWidth = ctx.measureText(this.author).width; ctx.fillText(this.author, 250, 140); ctx.fillStyle = randomColor(); ctx.fillText(this.requester, 250 + authorTextWidth + 10, 140); return frame.toBuffer("image/png"); } else { throw new Error('Invalid theme parameter, must be "peechu"'); } } } module.exports = { peechu };