Fix: 絵文字が正しくカウントされない問題 / Fix: 投稿できない問題 / Feat: 投稿の待機時間を表示

This commit is contained in:
2026-05-27 08:00:25 +09:00
parent 0fe88a36ab
commit dd4a5beb03
+31 -17
View File
@@ -17,7 +17,16 @@ type SuccessPosted<T = string> = {
}; };
} }
const BASE_URL = "https://collapse.jp/api/v3/bot/"; const getRealLength = (str: string): number => {
const segmenter = new Intl.Segmenter("ja", { granularity: "grapheme" });
return [...segmenter.segment(str)].length;
};
const realSlice = (str: string, limit: number): string => {
const segmenter = new Intl.Segmenter("ja", { granularity: "grapheme" });
const segments = [...segmenter.segment(str)];
return segments.slice(0, limit).map(s => s.segment).join("");
};
export const createPost = async (data: { export const createPost = async (data: {
text: string; text: string;
@@ -27,6 +36,9 @@ export const createPost = async (data: {
images?: [Blob, string][]; images?: [Blob, string][];
}, title: string) => { }, title: string) => {
const excessedMessage = "**👉返信に続きがあります。**"; const excessedMessage = "**👉返信に続きがあります。**";
const excessedMessageLength = getRealLength(excessedMessage);
const eolLength = getRealLength(EOL);
let lines = data.text.split(EOL); let lines = data.text.split(EOL);
let firstUniqid = ""; let firstUniqid = "";
@@ -40,23 +52,25 @@ export const createPost = async (data: {
const maxLength = config.post.maxLength; const maxLength = config.post.maxLength;
const limit = maxLength - (excessedMessage.length + EOL.length * 2); const limit = maxLength - (excessedMessageLength + eolLength * 2);
while (lines.length > 0) { while (lines.length > 0) {
const nextLine = lines[0]; const nextLine = lines[0];
if (nextLine === undefined) if (nextLine === undefined)
break; break;
if (nextLine.length > limit && currentText === "") { const nextLineLength = getRealLength(nextLine);
if (nextLineLength > limit && currentText === "") {
const targetLine = lines.shift() || ""; const targetLine = lines.shift() || "";
currentText = targetLine.slice(0, limit); currentText = realSlice(targetLine, limit);
lines.unshift(realSlice(targetLine, limit * -1));
lines.unshift(targetLine.slice(limit));
break; break;
} }
const potentialText = currentText ? currentText + EOL + nextLine : nextLine; const potentialText = currentText
if (potentialText.length <= limit) { ? currentText + EOL + nextLine
: nextLine;
if (getRealLength(potentialText) <= limit) {
currentText = potentialText; currentText = potentialText;
lines.shift(); lines.shift();
} else { } else {
@@ -79,25 +93,24 @@ export const createPost = async (data: {
? firstUniqid ? firstUniqid
: data.replyid; : data.replyid;
const body = new FormData(); const formData = new FormData();
body.append("content", data.text); formData.append("content", currentText);
body.append("zone", data.zone ?? "normal"); formData.append("zone", data.zone ?? "normal");
body.append("reply_restriction", data.replyTarget ?? "all"); formData.append("reply_restriction", data.replyTarget ?? "all");
if (replyid) { if (replyid) {
body.append("reply_to_id", replyid); formData.append("reply_to_id", replyid);
} }
if (data.images) { if (data.images) {
data.images.forEach(img => body.append("images", img[0], img[1])); data.images.forEach(img => formData.append("images", img[0], img[1]));
} }
const req = await fetch(new URL("posts", BASE_URL), { const req = await fetch(`https://collapse.jp/api/v3/bot/posts`, {
method: "POST", method: "POST",
body,
headers: { headers: {
"Authorization": `Bearer ${config.mtweet.token}`, "Authorization": `Bearer ${config.mtweet.token}`,
"Content-Type": "application/json",
"X-Idempotency-Key": String(process.hrtime.bigint()), "X-Idempotency-Key": String(process.hrtime.bigint()),
}, },
body: formData,
}); });
const res = await req.json(); const res = await req.json();
@@ -114,6 +127,7 @@ export const createPost = async (data: {
const interval = res.error.details?.retry_after const interval = res.error.details?.retry_after
? res.error.details.retry_after * 1000 ? res.error.details.retry_after * 1000
: config.post.retryInterval; : config.post.retryInterval;
console.log(`${interval}ms待機します...`);
await new Promise(resolve => setTimeout(resolve, interval)); await new Promise(resolve => setTimeout(resolve, interval));
} }
} catch (err) { } catch (err) {