karin-plugin-kkk 1.0.4-commit.db43730 → 1.0.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.4](https://github.com/ikenxuan/karin-plugin-kkk/compare/v1.0.3...v1.0.4) (2025-01-19)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * ci ([2cc5cbb](https://github.com/ikenxuan/karin-plugin-kkk/commit/2cc5cbb7ecca8b581905a6e5e5cbbb1e5dd6a829))
9
+ * 细优 ([73b5562](https://github.com/ikenxuan/karin-plugin-kkk/commit/73b55621405a05e5e88e05aed7a3af28ab05eb8b))
10
+
11
+
12
+ ### Performance Improvements
13
+
14
+ * 优化合辑解析 ([a2a75b4](https://github.com/ikenxuan/karin-plugin-kkk/commit/a2a75b423525180ea7f03f9112893640dea12238))
15
+
3
16
  ## [1.0.3](https://github.com/ikenxuan/karin-plugin-kkk/compare/1.0.2-commit.ced194c...v1.0.3-commit.ced194c) (2025-01-16)
4
17
 
5
18
 
@@ -3,6 +3,6 @@ export declare const bilibiliPush: false | import("node-karin").Task;
3
3
  export declare const forcePush: import("node-karin").Command<"message.group">;
4
4
  export declare const setdyPush: import("node-karin").Command<"message.group">;
5
5
  export declare const setbiliPush: import("node-karin").Command<"message.group">;
6
- export declare const bilibiliPushList: import("node-karin").Command<keyof import("node-karin").MessageEventMap>;
7
- export declare const douyinPushList: import("node-karin").Command<keyof import("node-karin").MessageEventMap>;
6
+ export declare const bilibiliPushList: import("node-karin").Command<"message.group">;
7
+ export declare const douyinPushList: import("node-karin").Command<"message.group">;
8
8
  export declare const changeBotID: import("node-karin").Command<keyof import("node-karin").MessageEventMap>;
package/lib/apps/push.js CHANGED
@@ -37,10 +37,10 @@ export const setbiliPush = karin.command(/^#设置[bB]站推送(?:[Uu][Ii][Dd]:)
37
37
  }, { name: 'kkk-推送功能-设置', event: 'message.group', perm: Config.bilibili.push.permission, dsbAdapter: ['qqbot'] });
38
38
  export const bilibiliPushList = karin.command(/^#?[bB]站推送列表$/, async (e) => {
39
39
  await new Bilibilipush(e).renderPushList(Config.pushlist.bilibili);
40
- });
40
+ }, { name: 'kkk-推送功能-列表', event: 'message.group' });
41
41
  export const douyinPushList = karin.command(/^#?抖音推送列表$/, async (e) => {
42
42
  await new DouYinpush(e).renderPushList(Config.pushlist.douyin);
43
- });
43
+ }, { name: 'kkk-推送功能-列表', event: 'message.group' });
44
44
  export const changeBotID = karin.command(/^#kkk设置推送机器人/, async (e) => {
45
45
  const newDouyinlist = Config.pushlist.douyin.map(item => {
46
46
  // 操作每个 group_id
package/lib/cli/pr.js CHANGED
@@ -14,16 +14,15 @@ const readPkg = () => JSON.parse(fs.readFileSync(getPkgPath(), 'utf-8'));
14
14
  */
15
15
  const writePkg = (pkg) => fs.writeFileSync(getPkgPath(), JSON.stringify(pkg, null, 2));
16
16
  /**
17
- * @description 构建pr版本号 <主版本号>.<次版本号>.<修订号>.<PR标识PR编号>.<当前提交唯一短哈希>
17
+ * @description 构建pr版本号 <主版本号>.<次版本号>.<修订号>.<PR标识>.<PR编号>.<当前提交唯一短哈希>
18
18
  * @example 1.0.0.pr.184.a1b2c3d
19
19
  * @param pkg package.json
20
20
  */
21
21
  const updateVersion = (pkg) => {
22
22
  const list = pkg.version.split('.');
23
- console.log('PR_COMMIT_HASH' + process.env.PR_COMMIT_HASH);
24
- const shortHash = process.env.PR_COMMIT_HASH?.substring(0, 7) ?? 'unknown';
23
+ const shortHash = process.env.GITHUB_SHA?.substring(0, 7) ?? 'unknown';
25
24
  list[2] = `${Number(list[2]) + 1}`;
26
- pkg.version = `${list.join('.')}-pr${process.env.PR_NUMBER}.${shortHash}`;
25
+ pkg.version = `${list.join('.')}.pr.${process.env.PR_NUMBER}.${shortHash}`;
27
26
  };
28
27
  /**
29
28
  * @description 设置环境变量
@@ -1,5 +1,5 @@
1
1
  import { Message } from 'node-karin';
2
- interface uploadFileOptions {
2
+ type uploadFileOptions = {
3
3
  /** 是否使用群文件上传 */
4
4
  useGroupFile?: boolean;
5
5
  /** 消息ID,如果有,则将使用该消息ID制作回复元素 */
@@ -13,15 +13,15 @@ interface uploadFileOptions {
13
13
  /** 群号 */
14
14
  group_id: string;
15
15
  };
16
- }
16
+ };
17
17
  /** 最少都要传一个 */
18
- interface title {
18
+ type title = {
19
19
  /** 文件名:自定义 */
20
20
  originTitle?: string;
21
21
  /** 文件名:tmp + 时间戳 */
22
22
  timestampTitle?: string;
23
- }
24
- interface downloadFileOptions {
23
+ };
24
+ type downloadFileOptions = {
25
25
  /** 视频链接 */
26
26
  video_url: string;
27
27
  /** 文件名 */
@@ -30,8 +30,8 @@ interface downloadFileOptions {
30
30
  filetype?: string;
31
31
  /** 自定义请求头,将使用该请求头下载文件。 */
32
32
  headers?: object;
33
- }
34
- interface fileInfo {
33
+ };
34
+ export type fileInfo = {
35
35
  /** 视频文件的绝对路径 */
36
36
  filepath: string;
37
37
  /** 视频文件大小 */
@@ -40,8 +40,8 @@ interface fileInfo {
40
40
  originTitle?: title['originTitle'];
41
41
  /** 文件名:tmp + 时间戳 */
42
42
  timestampTitle?: title['timestampTitle'];
43
- }
44
- interface downLoadFileOptions {
43
+ };
44
+ type downLoadFileOptions = {
45
45
  /** 文件名 */
46
46
  title: string;
47
47
  /**
@@ -49,7 +49,7 @@ interface downLoadFileOptions {
49
49
  * @default {}
50
50
  */
51
51
  headers?: object;
52
- }
52
+ };
53
53
  export declare class Base {
54
54
  e: Message;
55
55
  headers: any;
@@ -43,11 +43,27 @@ export declare class Bilibili extends Base {
43
43
  }>;
44
44
  }
45
45
  export declare function replacetext(text: string, rich_text_nodes: any[]): string;
46
+ /**
47
+ * 拼接B站动态卡片的html字符串
48
+ * @param colors 颜色数组
49
+ * @param text 卡片的文字
50
+ * @returns 拼接好的html字符串
51
+ */
46
52
  export declare const generateGradientStyle: (colors: string[], text: string) => string;
53
+ /**
54
+ * 将给定的图片源数组转换为一个新的对象数组,每个对象包含单个图片源
55
+ * @param pic 一个包含图片源字符串的数组
56
+ * @returns 返回一个对象数组,每个对象包含单个图片源
57
+ */
47
58
  export declare const cover: (pic: {
48
59
  img_src: string;
49
60
  }[]) => {
50
61
  image_src: string;
51
62
  }[];
63
+ /**
64
+ * 生成装饰卡片的HTML字符串
65
+ * @param decorate 装饰对象,包含卡片的URL和颜色信息
66
+ * @returns 返回装饰卡片的HTML字符串或空div字符串
67
+ */
52
68
  export declare const generateDecorationCard: (decorate: any) => string;
53
69
  export {};
@@ -599,6 +599,12 @@ const qnd = {
599
599
  126: '杜比视界',
600
600
  127: '超高清 8K'
601
601
  };
602
+ /**
603
+ * 拼接B站动态卡片的html字符串
604
+ * @param colors 颜色数组
605
+ * @param text 卡片的文字
606
+ * @returns 拼接好的html字符串
607
+ */
602
608
  export const generateGradientStyle = (colors, text) => {
603
609
  if (!colors)
604
610
  return '';
@@ -608,6 +614,11 @@ export const generateGradientStyle = (colors, text) => {
608
614
  // 返回完整的CSS样式字符串
609
615
  return `<span style="font-family: bilifont; color: transparent; background-clip: text; margin: 0 200px 0 0; font-size: 43px; background-image: linear-gradient(135deg, ${gradientString} 0%, ${gradientString} 100%); ">${text}</span>`;
610
616
  };
617
+ /**
618
+ * 将给定的图片源数组转换为一个新的对象数组,每个对象包含单个图片源
619
+ * @param pic 一个包含图片源字符串的数组
620
+ * @returns 返回一个对象数组,每个对象包含单个图片源
621
+ */
611
622
  export const cover = (pic) => {
612
623
  const imgArray = [];
613
624
  for (const i of pic) {
@@ -618,6 +629,11 @@ export const cover = (pic) => {
618
629
  }
619
630
  return imgArray;
620
631
  };
632
+ /**
633
+ * 生成装饰卡片的HTML字符串
634
+ * @param decorate 装饰对象,包含卡片的URL和颜色信息
635
+ * @returns 返回装饰卡片的HTML字符串或空div字符串
636
+ */
621
637
  export const generateDecorationCard = (decorate) => {
622
638
  return decorate
623
639
  ? `<div style="display: flex; width: 500px; height: 150px; background-position: center; background-attachment: fixed; background-repeat: no-repeat; background-size: contain; align-items: center; justify-content: flex-end; background-image: url('${decorate.card_url}')">${generateGradientStyle(decorate.fan?.color_format?.colors, decorate.fan.num_str)}</div>`
@@ -136,26 +136,40 @@ export class DouYin extends Base {
136
136
  return true;
137
137
  }
138
138
  case 'user_mix_videos': {
139
+ const emojiData = await getDouyinData('Emoji数据');
140
+ const commentsData = await douyinComments(data.CommentsData, emojiData);
141
+ const commentImage = await Render('douyin/comment', {
142
+ Type: '合辑作品',
143
+ CommentsData: commentsData,
144
+ CommentLength: String(commentsData.jsonArray?.length ? commentsData.jsonArray.length : 0),
145
+ share_url: this.is_mp4
146
+ ? `https://aweme.snssdk.com/aweme/v1/play/?video_id=${data.VideoData.aweme_detail.video.play_addr.uri}&ratio=1080p&line=0`
147
+ : data.VideoData.aweme_detail.share_url,
148
+ VideoSize: '???',
149
+ VideoFPS: '???',
150
+ ImageLength: '???'
151
+ });
152
+ await this.e.reply(commentImage);
139
153
  const images = [];
140
- const bgmurl = data.aweme_details[0].music.play_url.uri;
141
- for (const item of data.aweme_details[0].images) {
154
+ const temp = [];
155
+ /** BGM */
156
+ const liveimgbgm = await this.DownLoadFile(data.LiveImageData.aweme_details[0].music.play_url.uri, {
157
+ title: `Douyin_tmp_A_${Date.now()}.mp3`,
158
+ headers: this.headers
159
+ });
160
+ temp.push(liveimgbgm);
161
+ for (const item of data.LiveImageData.aweme_details[0].images) {
142
162
  // 静态图片,clip_type为2
143
163
  if (item.clip_type === 2) {
144
- images.push(segment.text(`动图直链:\nhttps://aweme.snssdk.com/aweme/v1/play/?video_id=${item.uri}&ratio=1080p&line=0`));
164
+ images.push(segment.image((item.url_list[0])));
145
165
  continue;
146
166
  }
147
- images.push(segment.text(`动图直链:\nhttps://aweme.snssdk.com/aweme/v1/play/?video_id=${item.video.play_addr_h264.uri}&ratio=1080p&line=0`));
148
- // 动图
167
+ /** 动图 */
149
168
  const liveimg = await this.DownLoadFile(`https://aweme.snssdk.com/aweme/v1/play/?video_id=${item.video.play_addr_h264.uri}&ratio=1080p&line=0`, {
150
169
  title: `Douyin_tmp_V_${Date.now()}.mp4`,
151
170
  headers: this.headers
152
171
  });
153
- // BGM
154
- const liveimgbgm = await this.DownLoadFile(bgmurl, {
155
- title: `Douyin_tmp_A_${Date.now()}.mp3`,
156
- headers: this.headers
157
- });
158
- if (liveimg.filepath && liveimgbgm.filepath) {
172
+ if (liveimg.filepath) {
159
173
  const resolvefilepath = Common.tempDri.video + `Douyin_Result_${Date.now()}.mp4`;
160
174
  await mergeFile('视频*3 + 音频', {
161
175
  path: liveimg.filepath,
@@ -165,21 +179,12 @@ export class DouYin extends Base {
165
179
  if (success) {
166
180
  const filePath = Common.tempDri.video + `tmp_${Date.now()}.mp4`;
167
181
  fs.renameSync(resultPath, filePath);
168
- await this.removeFile(liveimgbgm.filepath, true);
169
182
  await this.removeFile(liveimg.filepath, true);
170
- const stats = fs.statSync(filePath);
171
- const fileSizeInMB = Number((stats.size / (1024 * 1024)).toFixed(2));
172
- if (fileSizeInMB > Config.upload.groupfilevalue) {
173
- this.e.reply(`视频大小: ${fileSizeInMB}MB 正通过群文件上传中...`);
174
- return await this.upload_file({ filepath: filePath, totalBytes: fileSizeInMB }, '', { useGroupFile: true });
175
- }
176
- else {
177
- /** 因为本地合成,没有视频直链 */
178
- return await this.upload_file({ filepath: filePath, totalBytes: fileSizeInMB }, '');
179
- }
183
+ temp.push({ filepath: filePath, totalBytes: 0 });
184
+ images.push(segment.video('file://' + filePath));
185
+ return true;
180
186
  }
181
187
  else {
182
- await this.removeFile(liveimgbgm.filepath, true);
183
188
  await this.removeFile(liveimg.filepath, true);
184
189
  return true;
185
190
  }
@@ -188,7 +193,17 @@ export class DouYin extends Base {
188
193
  }
189
194
  }
190
195
  const Element = common.makeForward(images, this.e.sender.userId, this.e.sender.nick);
191
- await this.e.bot.sendForwardMsg(this.e.contact, Element);
196
+ try {
197
+ await this.e.bot.sendForwardMsg(this.e.contact, Element);
198
+ }
199
+ catch (error) {
200
+ await this.e.reply(JSON.stringify(error, null, 2));
201
+ }
202
+ finally {
203
+ for (const item of temp) {
204
+ await this.removeFile(item.filepath, true);
205
+ }
206
+ }
192
207
  return true;
193
208
  }
194
209
  case 'user_dynamic': {
@@ -23,10 +23,14 @@ export async function fetchDouyinData(type, opt) {
23
23
  return CommentsData;
24
24
  }
25
25
  case 'user_mix_videos': {
26
+ const CommentsData = await getDouyinData('评论数据', dyck, {
27
+ aweme_id: opt.aweme_id,
28
+ number: Config.douyin.numcomment
29
+ });
26
30
  const LiveImageData = await getDouyinData('合辑作品数据', dyck, {
27
31
  aweme_id: opt.aweme_id
28
32
  });
29
- return LiveImageData;
33
+ return { LiveImageData, CommentsData };
30
34
  }
31
35
  case 'live_room_detail':
32
36
  case 'user_profile': {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "karin-plugin-kkk",
3
- "version": "1.0.4-commit.db43730",
3
+ "version": "1.0.4",
4
4
  "description": "a Karin video parsing tool",
5
5
  "keywords": [
6
6
  "karin-plugin",
@@ -45,17 +45,17 @@
45
45
  "log": "karin log",
46
46
  "up": "karin up",
47
47
  "init": "karin init",
48
- "dev": "tsx watch --include \"./src/**/*\" node_modules/node-karin/dist/index.js",
48
+ "dev": "tsx watch --include \"src/**/*.ts\" src/index.ts",
49
49
  "ts": "karin ts",
50
50
  "watch": "karin watch"
51
51
  },
52
52
  "dependencies": {
53
- "@ikenxuan/amagi": "4.2.3",
53
+ "@ikenxuan/amagi": "4.2.4",
54
54
  "@karinjs/md-html": "^1.1.6",
55
55
  "cors": "^2.8.5",
56
56
  "heic-convert": "^2.1.0",
57
57
  "http-proxy-middleware": "^3.0.3",
58
- "playwright": "^1.49.0",
58
+ "playwright": "^1.49.1",
59
59
  "qrcode": "^1.5.4",
60
60
  "sequelize": "6.37.3",
61
61
  "sqlite3": "5.1.6"