koishi-plugin-bilibili-notify 3.2.8-alpha.2 → 3.2.9-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +126 -3
- package/lib/index.mjs +126 -3
- package/package.json +2 -1
- package/readme.md +4 -0
package/lib/index.js
CHANGED
|
@@ -39,6 +39,7 @@ const path = __toESM$1(require("path"));
|
|
|
39
39
|
const qrcode = __toESM$1(require("qrcode"));
|
|
40
40
|
const cron = __toESM$1(require("cron"));
|
|
41
41
|
const luxon = __toESM$1(require("luxon"));
|
|
42
|
+
const segmentit = __toESM$1(require("segmentit"));
|
|
42
43
|
const __satorijs_element_jsx_runtime = __toESM$1(require("@satorijs/element/jsx-runtime"));
|
|
43
44
|
const node_path = __toESM$1(require("node:path"));
|
|
44
45
|
const node_url = __toESM$1(require("node:url"));
|
|
@@ -646,6 +647,7 @@ var ComRegister = class {
|
|
|
646
647
|
privateBot;
|
|
647
648
|
dynamicJob;
|
|
648
649
|
liveJob;
|
|
650
|
+
_segmentit = (0, segmentit.useDefault)(new segmentit.Segment());
|
|
649
651
|
constructor(ctx, config) {
|
|
650
652
|
this.ctx = ctx;
|
|
651
653
|
this.init(config);
|
|
@@ -1221,10 +1223,16 @@ var ComRegister = class {
|
|
|
1221
1223
|
const msg = /* @__PURE__ */ (0, __satorijs_element_jsx_runtime.jsxs)("message", { children: [koishi.h.image(buffer, "image/jpeg"), liveNotifyMsg || ""] });
|
|
1222
1224
|
return await this.broadcastToTargets(uid, msg, liveType === LiveType.StartBroadcasting ? PushType.StartBroadcasting : PushType.Live);
|
|
1223
1225
|
}
|
|
1226
|
+
async segmentDanmaku(danmaku, danmakuWeightRecord) {
|
|
1227
|
+
this._segmentit.doSegment(danmaku).map(({ w: w$3, p: p$1 }) => {
|
|
1228
|
+
if (p$1 && p$1 === 2048) return;
|
|
1229
|
+
danmakuWeightRecord[w$3] = (danmakuWeightRecord[w$3] || 0) + 1;
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1224
1232
|
async liveDetectWithListener(roomId, uid, cardStyle) {
|
|
1225
1233
|
let liveTime;
|
|
1226
1234
|
let pushAtTimeTimer;
|
|
1227
|
-
const
|
|
1235
|
+
const danmakuWeightRecord = {};
|
|
1228
1236
|
let liveStatus = false;
|
|
1229
1237
|
let liveRoomInfo;
|
|
1230
1238
|
let masterInfo;
|
|
@@ -1275,10 +1283,10 @@ var ComRegister = class {
|
|
|
1275
1283
|
this.logger.error(`[${roomId}]直播间连接发生错误!`);
|
|
1276
1284
|
},
|
|
1277
1285
|
onIncomeDanmu: ({ body }) => {
|
|
1278
|
-
|
|
1286
|
+
this.segmentDanmaku(body.content, danmakuWeightRecord);
|
|
1279
1287
|
},
|
|
1280
1288
|
onIncomeSuperChat: ({ body }) => {
|
|
1281
|
-
|
|
1289
|
+
this.segmentDanmaku(body.content, danmakuWeightRecord);
|
|
1282
1290
|
},
|
|
1283
1291
|
onWatchedChange: ({ body }) => {
|
|
1284
1292
|
watchedNum = body.text_small;
|
|
@@ -1333,6 +1341,9 @@ var ComRegister = class {
|
|
|
1333
1341
|
}, uid, liveEndMsg);
|
|
1334
1342
|
pushAtTimeTimer();
|
|
1335
1343
|
pushAtTimeTimer = null;
|
|
1344
|
+
const words = Object.entries(danmakuWeightRecord);
|
|
1345
|
+
const buffer = await this.ctx.gi.generateWordCloudImg(words, masterInfo.username);
|
|
1346
|
+
await this.broadcastToTargets(uid, koishi.h.image(buffer, "image/jpeg"), PushType.Live);
|
|
1336
1347
|
}
|
|
1337
1348
|
};
|
|
1338
1349
|
await this.ctx.bl.startLiveRoomListener(roomId, handler);
|
|
@@ -94312,6 +94323,118 @@ var GenerateImg = class extends koishi.Service {
|
|
|
94312
94323
|
throw new Error(`生成图片失败!错误: ${e$1.toString()}`);
|
|
94313
94324
|
});
|
|
94314
94325
|
}
|
|
94326
|
+
async generateWordCloudImg(words, masterName) {
|
|
94327
|
+
const html = `
|
|
94328
|
+
<!DOCTYPE html>
|
|
94329
|
+
<html lang="zh-CN">
|
|
94330
|
+
|
|
94331
|
+
<head>
|
|
94332
|
+
<meta charset="UTF-8">
|
|
94333
|
+
<title>高清词云展示</title>
|
|
94334
|
+
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@500&display=swap" rel="stylesheet">
|
|
94335
|
+
<style>
|
|
94336
|
+
* {
|
|
94337
|
+
margin: 0;
|
|
94338
|
+
padding: 0;
|
|
94339
|
+
box-sizing: border-box;
|
|
94340
|
+
}
|
|
94341
|
+
|
|
94342
|
+
html {
|
|
94343
|
+
width: 720px;
|
|
94344
|
+
height: 520px;
|
|
94345
|
+
}
|
|
94346
|
+
|
|
94347
|
+
.wordcloud-bg {
|
|
94348
|
+
width: 720px;
|
|
94349
|
+
height: 520px;
|
|
94350
|
+
background: linear-gradient(to right, #e0eafc, #cfdef3);
|
|
94351
|
+
font-family: 'Quicksand', sans-serif;
|
|
94352
|
+
display: flex;
|
|
94353
|
+
justify-content: center;
|
|
94354
|
+
align-items: center;
|
|
94355
|
+
}
|
|
94356
|
+
|
|
94357
|
+
.wordcloud-card {
|
|
94358
|
+
width: 700px;
|
|
94359
|
+
height: 500px;
|
|
94360
|
+
backdrop-filter: blur(10px);
|
|
94361
|
+
background: rgba(255, 255, 255, 0.25);
|
|
94362
|
+
border-radius: 20px;
|
|
94363
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
|
94364
|
+
padding: 20px;
|
|
94365
|
+
display: flex;
|
|
94366
|
+
flex-direction: column;
|
|
94367
|
+
align-items: center;
|
|
94368
|
+
justify-content: center;
|
|
94369
|
+
}
|
|
94370
|
+
|
|
94371
|
+
h2 {
|
|
94372
|
+
margin: 0 0 10px;
|
|
94373
|
+
color: #333;
|
|
94374
|
+
font-size: 24px;
|
|
94375
|
+
}
|
|
94376
|
+
|
|
94377
|
+
canvas {
|
|
94378
|
+
width: 100%;
|
|
94379
|
+
height: 100%;
|
|
94380
|
+
display: block;
|
|
94381
|
+
}
|
|
94382
|
+
</style>
|
|
94383
|
+
</head>
|
|
94384
|
+
|
|
94385
|
+
<body>
|
|
94386
|
+
<div class="wordcloud-bg">
|
|
94387
|
+
<div class="wordcloud-card">
|
|
94388
|
+
<h2>${masterName}直播弹幕词云</h2>
|
|
94389
|
+
<canvas id="wordCloudCanvas"></canvas>
|
|
94390
|
+
</div>
|
|
94391
|
+
</div>
|
|
94392
|
+
|
|
94393
|
+
<script src="https://cdn.jsdelivr.net/npm/wordcloud@1.1.2/src/wordcloud2.min.js"></script>
|
|
94394
|
+
<script>
|
|
94395
|
+
const canvas = document.getElementById('wordCloudCanvas');
|
|
94396
|
+
const ctx = canvas.getContext('2d');
|
|
94397
|
+
|
|
94398
|
+
// 获取 CSS 大小
|
|
94399
|
+
const style = getComputedStyle(canvas);
|
|
94400
|
+
const cssWidth = parseInt(style.width);
|
|
94401
|
+
const cssHeight = parseInt(style.height);
|
|
94402
|
+
const ratio = window.devicePixelRatio || 1;
|
|
94403
|
+
|
|
94404
|
+
// 设置 canvas 分辨率 & 缩放
|
|
94405
|
+
canvas.width = cssWidth * ratio;
|
|
94406
|
+
canvas.height = cssHeight * ratio;
|
|
94407
|
+
ctx.scale(ratio, ratio);
|
|
94408
|
+
|
|
94409
|
+
const words = ${JSON.stringify(words)}
|
|
94410
|
+
|
|
94411
|
+
WordCloud(canvas, {
|
|
94412
|
+
list: words,
|
|
94413
|
+
gridSize: Math.round(8 * (cssWidth / 1024)), // 自动适配大小
|
|
94414
|
+
weightFactor: size => size * (cssWidth / 1024) * 1.2,
|
|
94415
|
+
fontFamily: 'Quicksand, sans-serif',
|
|
94416
|
+
color: () => {
|
|
94417
|
+
const colors = ['#007CF0', '#00DFD8', '#7928CA', '#FF0080', '#FF4D4D', '#F9CB28'];
|
|
94418
|
+
return colors[Math.floor(Math.random() * colors.length)];
|
|
94419
|
+
},
|
|
94420
|
+
rotateRatio: 0.5,
|
|
94421
|
+
rotationSteps: 2,
|
|
94422
|
+
backgroundColor: 'transparent',
|
|
94423
|
+
drawOutOfBound: false,
|
|
94424
|
+
origin: [cssWidth / 2, cssHeight / 2], // 居中关键点
|
|
94425
|
+
// 明确告诉 wordcloud2 使用这个宽高(以 CSS 尺寸为准)
|
|
94426
|
+
width: cssWidth,
|
|
94427
|
+
height: cssHeight,
|
|
94428
|
+
});
|
|
94429
|
+
</script>
|
|
94430
|
+
</body>
|
|
94431
|
+
|
|
94432
|
+
</html>
|
|
94433
|
+
`;
|
|
94434
|
+
return await withRetry(() => this.imgHandler(html)).catch((e$1) => {
|
|
94435
|
+
throw new Error(`生成图片失败!错误: ${e$1.toString()}`);
|
|
94436
|
+
});
|
|
94437
|
+
}
|
|
94315
94438
|
async getLiveStatus(time, liveStatus) {
|
|
94316
94439
|
let titleStatus;
|
|
94317
94440
|
let liveTime;
|
package/lib/index.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { resolve } from "path";
|
|
|
4
4
|
import QRCode from "qrcode";
|
|
5
5
|
import { CronJob } from "cron";
|
|
6
6
|
import { DateTime } from "luxon";
|
|
7
|
+
import { Segment, useDefault } from "segmentit";
|
|
7
8
|
import { Fragment, jsx, jsxs } from "@satorijs/element/jsx-runtime";
|
|
8
9
|
import { resolve as resolve$1 } from "node:path";
|
|
9
10
|
import { pathToFileURL } from "node:url";
|
|
@@ -648,6 +649,7 @@ var ComRegister = class {
|
|
|
648
649
|
privateBot;
|
|
649
650
|
dynamicJob;
|
|
650
651
|
liveJob;
|
|
652
|
+
_segmentit = useDefault(new Segment());
|
|
651
653
|
constructor(ctx, config) {
|
|
652
654
|
this.ctx = ctx;
|
|
653
655
|
this.init(config);
|
|
@@ -1223,10 +1225,16 @@ var ComRegister = class {
|
|
|
1223
1225
|
const msg = /* @__PURE__ */ jsxs("message", { children: [h.image(buffer, "image/jpeg"), liveNotifyMsg || ""] });
|
|
1224
1226
|
return await this.broadcastToTargets(uid, msg, liveType === LiveType.StartBroadcasting ? PushType.StartBroadcasting : PushType.Live);
|
|
1225
1227
|
}
|
|
1228
|
+
async segmentDanmaku(danmaku, danmakuWeightRecord) {
|
|
1229
|
+
this._segmentit.doSegment(danmaku).map(({ w: w$3, p: p$1 }) => {
|
|
1230
|
+
if (p$1 && p$1 === 2048) return;
|
|
1231
|
+
danmakuWeightRecord[w$3] = (danmakuWeightRecord[w$3] || 0) + 1;
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1226
1234
|
async liveDetectWithListener(roomId, uid, cardStyle) {
|
|
1227
1235
|
let liveTime;
|
|
1228
1236
|
let pushAtTimeTimer;
|
|
1229
|
-
const
|
|
1237
|
+
const danmakuWeightRecord = {};
|
|
1230
1238
|
let liveStatus = false;
|
|
1231
1239
|
let liveRoomInfo;
|
|
1232
1240
|
let masterInfo;
|
|
@@ -1277,10 +1285,10 @@ var ComRegister = class {
|
|
|
1277
1285
|
this.logger.error(`[${roomId}]直播间连接发生错误!`);
|
|
1278
1286
|
},
|
|
1279
1287
|
onIncomeDanmu: ({ body }) => {
|
|
1280
|
-
|
|
1288
|
+
this.segmentDanmaku(body.content, danmakuWeightRecord);
|
|
1281
1289
|
},
|
|
1282
1290
|
onIncomeSuperChat: ({ body }) => {
|
|
1283
|
-
|
|
1291
|
+
this.segmentDanmaku(body.content, danmakuWeightRecord);
|
|
1284
1292
|
},
|
|
1285
1293
|
onWatchedChange: ({ body }) => {
|
|
1286
1294
|
watchedNum = body.text_small;
|
|
@@ -1335,6 +1343,9 @@ var ComRegister = class {
|
|
|
1335
1343
|
}, uid, liveEndMsg);
|
|
1336
1344
|
pushAtTimeTimer();
|
|
1337
1345
|
pushAtTimeTimer = null;
|
|
1346
|
+
const words = Object.entries(danmakuWeightRecord);
|
|
1347
|
+
const buffer = await this.ctx.gi.generateWordCloudImg(words, masterInfo.username);
|
|
1348
|
+
await this.broadcastToTargets(uid, h.image(buffer, "image/jpeg"), PushType.Live);
|
|
1338
1349
|
}
|
|
1339
1350
|
};
|
|
1340
1351
|
await this.ctx.bl.startLiveRoomListener(roomId, handler);
|
|
@@ -94314,6 +94325,118 @@ var GenerateImg = class extends Service {
|
|
|
94314
94325
|
throw new Error(`生成图片失败!错误: ${e$1.toString()}`);
|
|
94315
94326
|
});
|
|
94316
94327
|
}
|
|
94328
|
+
async generateWordCloudImg(words, masterName) {
|
|
94329
|
+
const html = `
|
|
94330
|
+
<!DOCTYPE html>
|
|
94331
|
+
<html lang="zh-CN">
|
|
94332
|
+
|
|
94333
|
+
<head>
|
|
94334
|
+
<meta charset="UTF-8">
|
|
94335
|
+
<title>高清词云展示</title>
|
|
94336
|
+
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@500&display=swap" rel="stylesheet">
|
|
94337
|
+
<style>
|
|
94338
|
+
* {
|
|
94339
|
+
margin: 0;
|
|
94340
|
+
padding: 0;
|
|
94341
|
+
box-sizing: border-box;
|
|
94342
|
+
}
|
|
94343
|
+
|
|
94344
|
+
html {
|
|
94345
|
+
width: 720px;
|
|
94346
|
+
height: 520px;
|
|
94347
|
+
}
|
|
94348
|
+
|
|
94349
|
+
.wordcloud-bg {
|
|
94350
|
+
width: 720px;
|
|
94351
|
+
height: 520px;
|
|
94352
|
+
background: linear-gradient(to right, #e0eafc, #cfdef3);
|
|
94353
|
+
font-family: 'Quicksand', sans-serif;
|
|
94354
|
+
display: flex;
|
|
94355
|
+
justify-content: center;
|
|
94356
|
+
align-items: center;
|
|
94357
|
+
}
|
|
94358
|
+
|
|
94359
|
+
.wordcloud-card {
|
|
94360
|
+
width: 700px;
|
|
94361
|
+
height: 500px;
|
|
94362
|
+
backdrop-filter: blur(10px);
|
|
94363
|
+
background: rgba(255, 255, 255, 0.25);
|
|
94364
|
+
border-radius: 20px;
|
|
94365
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
|
94366
|
+
padding: 20px;
|
|
94367
|
+
display: flex;
|
|
94368
|
+
flex-direction: column;
|
|
94369
|
+
align-items: center;
|
|
94370
|
+
justify-content: center;
|
|
94371
|
+
}
|
|
94372
|
+
|
|
94373
|
+
h2 {
|
|
94374
|
+
margin: 0 0 10px;
|
|
94375
|
+
color: #333;
|
|
94376
|
+
font-size: 24px;
|
|
94377
|
+
}
|
|
94378
|
+
|
|
94379
|
+
canvas {
|
|
94380
|
+
width: 100%;
|
|
94381
|
+
height: 100%;
|
|
94382
|
+
display: block;
|
|
94383
|
+
}
|
|
94384
|
+
</style>
|
|
94385
|
+
</head>
|
|
94386
|
+
|
|
94387
|
+
<body>
|
|
94388
|
+
<div class="wordcloud-bg">
|
|
94389
|
+
<div class="wordcloud-card">
|
|
94390
|
+
<h2>${masterName}直播弹幕词云</h2>
|
|
94391
|
+
<canvas id="wordCloudCanvas"></canvas>
|
|
94392
|
+
</div>
|
|
94393
|
+
</div>
|
|
94394
|
+
|
|
94395
|
+
<script src="https://cdn.jsdelivr.net/npm/wordcloud@1.1.2/src/wordcloud2.min.js"></script>
|
|
94396
|
+
<script>
|
|
94397
|
+
const canvas = document.getElementById('wordCloudCanvas');
|
|
94398
|
+
const ctx = canvas.getContext('2d');
|
|
94399
|
+
|
|
94400
|
+
// 获取 CSS 大小
|
|
94401
|
+
const style = getComputedStyle(canvas);
|
|
94402
|
+
const cssWidth = parseInt(style.width);
|
|
94403
|
+
const cssHeight = parseInt(style.height);
|
|
94404
|
+
const ratio = window.devicePixelRatio || 1;
|
|
94405
|
+
|
|
94406
|
+
// 设置 canvas 分辨率 & 缩放
|
|
94407
|
+
canvas.width = cssWidth * ratio;
|
|
94408
|
+
canvas.height = cssHeight * ratio;
|
|
94409
|
+
ctx.scale(ratio, ratio);
|
|
94410
|
+
|
|
94411
|
+
const words = ${JSON.stringify(words)}
|
|
94412
|
+
|
|
94413
|
+
WordCloud(canvas, {
|
|
94414
|
+
list: words,
|
|
94415
|
+
gridSize: Math.round(8 * (cssWidth / 1024)), // 自动适配大小
|
|
94416
|
+
weightFactor: size => size * (cssWidth / 1024) * 1.2,
|
|
94417
|
+
fontFamily: 'Quicksand, sans-serif',
|
|
94418
|
+
color: () => {
|
|
94419
|
+
const colors = ['#007CF0', '#00DFD8', '#7928CA', '#FF0080', '#FF4D4D', '#F9CB28'];
|
|
94420
|
+
return colors[Math.floor(Math.random() * colors.length)];
|
|
94421
|
+
},
|
|
94422
|
+
rotateRatio: 0.5,
|
|
94423
|
+
rotationSteps: 2,
|
|
94424
|
+
backgroundColor: 'transparent',
|
|
94425
|
+
drawOutOfBound: false,
|
|
94426
|
+
origin: [cssWidth / 2, cssHeight / 2], // 居中关键点
|
|
94427
|
+
// 明确告诉 wordcloud2 使用这个宽高(以 CSS 尺寸为准)
|
|
94428
|
+
width: cssWidth,
|
|
94429
|
+
height: cssHeight,
|
|
94430
|
+
});
|
|
94431
|
+
</script>
|
|
94432
|
+
</body>
|
|
94433
|
+
|
|
94434
|
+
</html>
|
|
94435
|
+
`;
|
|
94436
|
+
return await withRetry(() => this.imgHandler(html)).catch((e$1) => {
|
|
94437
|
+
throw new Error(`生成图片失败!错误: ${e$1.toString()}`);
|
|
94438
|
+
});
|
|
94439
|
+
}
|
|
94317
94440
|
async getLiveStatus(time, liveStatus) {
|
|
94318
94441
|
let titleStatus;
|
|
94319
94442
|
let liveTime;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-bilibili-notify",
|
|
3
3
|
"description": "Koishi bilibili notify plugin",
|
|
4
|
-
"version": "3.2.
|
|
4
|
+
"version": "3.2.9-alpha.0",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Akokko <admin@akokko.com>"
|
|
7
7
|
],
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"luxon": "^3.6.1",
|
|
46
46
|
"md5": "^2.3.0",
|
|
47
47
|
"qrcode": "^1.5.4",
|
|
48
|
+
"segmentit": "^2.0.3",
|
|
48
49
|
"tough-cookie": "^5.1.2"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
package/readme.md
CHANGED