noticeUwuzu/miq/main.ts

135 lines
3.1 KiB
TypeScript

import { createCanvas, loadImage, registerFont } from "canvas";
import { writeFileSync } from "fs";
import sharp from "sharp";
import { MiQOptions } from "./miq";
function textReplace(
text: string
) {
let result = "";
// 改行削除
text = text.replaceAll("\n", "");
// 10文字/1回で改行を追加
let maxLength = 10;
if (text.length > maxLength) {
for (let i = 0; i < text.length; i += maxLength) {
result += text.substring(i, i + maxLength) + "\n";
}
result = result.trimEnd();
}
// 80文字以上は「...」で省略
maxLength = 80;
if (result.length > maxLength) {
result = result.substring(0, maxLength)
+ "...";
}
return result;
}
async function iconReplace(
color: boolean,
iconURL: string,
) {
let result = "";
const buffer = await(await fetch(iconURL, {
method: "GET",
cache: "no-store",
})).arrayBuffer();
if (color) {
const img = await sharp(Buffer.from(buffer))
.png()
.toBuffer();
result = `data:image/png;base64,${img.toString("base64")}`;
} else {
const img = await sharp(Buffer.from(buffer))
.png()
.grayscale()
.toBuffer();
result = `data:image/png;base64,${img.toString("base64")}`;
}
return result;
}
/**
* A function to generate
* Make it a quote on Node.js.
*/
export default async function MiQ({
type,
color,
text,
iconURL,
userName,
userID,
}: MiQOptions) {
// フォント読み込み
registerFont("miq/fonts/NotoSansJP.ttf", { family: "Noto Sans JP" });
// 初期化
const canvas = createCanvas(1200, 630);
const ctx = canvas.getContext("2d");
// 背景描画
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// アイコン描画
const iconImg = await loadImage(await iconReplace(
color,
iconURL,
));
const iconSize = canvas.height;
ctx.drawImage(iconImg, 0, 0, iconSize, iconSize);
// ユーザー名描画
ctx.font = "38px Noto Sans JP";
ctx.fillStyle = "white";
ctx.textAlign = "left";
ctx.textBaseline = "middle";
let x = 670;
let y = 480;
ctx.fillText("-", x, y);
ctx.fillText(userName, x+40, y, canvas.width-(x+40));
// ユーザーID描画
ctx.font = "28px Noto Sans JP";
ctx.fillStyle = "#3c3c3c";
ctx.fillText(`@${userID}`, x+120, y+50, canvas.width-(x+120));
// 本文描画
ctx.font = "48px Noto Sans JP";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = "white";
text = textReplace(text);
x = 870;
y = 30;
ctx.fillText(text, x, y+50);
// フェード描画
const fadeColor = "black";
const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop(0, "rgba(0, 0, 0, 0)");
gradient.addColorStop(0.5, fadeColor);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, iconSize, canvas.height);
// 返答
if (type === "Buffer") {
return canvas.toBuffer();
} else if (type === "Base64") {
return canvas.toDataURL();
} else {
return "Error: The type property is invalid.";
}
}