@dan-uni/dan-any-plugin-detaolu 0.0.2

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.
@@ -0,0 +1,28 @@
1
+ /*!
2
+ * The buffer module from node.js, for the browser.
3
+ *
4
+ * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
5
+ * @license MIT
6
+ */
7
+
8
+ /*!
9
+ * The buffer module from node.js, for the browser.
10
+ *
11
+ * @author Feross Aboukhadijeh <https://feross.org>
12
+ * @license MIT
13
+ */
14
+
15
+ /*! For license information please see index.umd.min.js.LICENSE.txt */
16
+
17
+ /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
18
+
19
+ /*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
20
+
21
+ /*! zero-fill. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
22
+
23
+ /**
24
+ * @author: xmcp(代码主要逻辑来源)
25
+ * @see: https://github.com/xmcp/pakku.js
26
+ * @license: GPL-3.0
27
+ * 本文件内代码来源见上,经部分修改,并整合config注释
28
+ */
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @author: xmcp(代码主要逻辑来源)
3
+ * @see: https://github.com/xmcp/pakku.js
4
+ * @license: GPL-3.0
5
+ * 本文件内代码来源见上,经部分修改,并整合config注释
6
+ */
7
+ import type { DanmuChunk, DanmuClusterOutput, DanmuObject } from './types';
8
+ export declare const DEFAULT_CONFIG: {
9
+ /**
10
+ * 时间阈值(合并n秒内的弹幕):
11
+ * 超长(大概 60 秒以上?)的阈值可能会导致程序运行缓慢
12
+ */
13
+ THRESHOLD: number;
14
+ /**
15
+ * 编辑距离合并阈值:
16
+ * 根据编辑距离判断不完全一致但内容相近(例如有错别字)的弹幕,
17
+ * 能有效击杀 "<code>你指尖跃动的电光</code>" 和 "<code>你<b>之间</b>跃动的电光</code>" 等
18
+ * @example 禁用(0),轻微(≤3),中等(≤5),强力(≤8)
19
+ */
20
+ MAX_DIST: number;
21
+ /**
22
+ * 词频向量合并阈值:
23
+ * 根据 2-Gram 频率向量的夹角判断不完全一致但内容类似的弹幕,
24
+ * 能有效击杀 "<code>yeah!~</code>" 和 "<code>yeah!~yeah!~yeah!~yeah!~</code>" 等
25
+ * @example 禁用(1000),轻微(60%),中等(45%),强力(30%)
26
+ */
27
+ MAX_COSINE: number;
28
+ /**
29
+ * 识别谐音弹幕:
30
+ * 将常用汉字转换为拼音再进行比较,
31
+ * 能有效击杀 "<code>布拉迪巴特福来</code>" 和 "<code>布拉迪·八德福莱</code>" 等
32
+ */
33
+ TRIM_PINYIN: boolean;
34
+ TRIM_ENDING: boolean;
35
+ TRIM_SPACE: boolean;
36
+ TRIM_WIDTH: boolean;
37
+ FORCELIST: string[][];
38
+ WHITELIST: [string, string][];
39
+ BLACKLIST: [string, string][];
40
+ CROSS_MODE: boolean;
41
+ PROC_TYPE7: boolean;
42
+ PROC_TYPE4: boolean;
43
+ PROC_POOL1: boolean;
44
+ };
45
+ export type Config = Partial<typeof DEFAULT_CONFIG>;
46
+ declare function merge(chunk: DanmuChunk<DanmuObject>, config?: Config): Promise<DanmuClusterOutput>;
47
+ export default merge;
@@ -0,0 +1,9 @@
1
+ import type { Config } from '.';
2
+ import type { int, Stats } from './types';
3
+ export declare function init(wasm_module: ArrayBuffer): Promise<void>;
4
+ export declare function begin_chunk(config: Config): void;
5
+ export declare function begin_index_lock(): void;
6
+ export declare function detect_similarity(str: string, mode: number, index_l: int, S: Stats): null | {
7
+ reason: string;
8
+ idx_diff: int;
9
+ };
@@ -0,0 +1,70 @@
1
+ import type { UniDM } from '@dan-uni/dan-any';
2
+ export type int = number;
3
+ export type float = number;
4
+ export type AnyObject = {
5
+ [k: string]: any;
6
+ };
7
+ export interface DanmuObject {
8
+ time_ms: int;
9
+ mode: int;
10
+ content: string;
11
+ pool: int;
12
+ danuni_dan: UniDM;
13
+ }
14
+ export interface DanmuObjectPeer extends DanmuObject {
15
+ pakku: {
16
+ sim_reason: string;
17
+ };
18
+ }
19
+ export interface DanmuObjectRepresentative extends DanmuObject {
20
+ pakku: {
21
+ peers: DanmuObjectPeer[];
22
+ desc: string[];
23
+ disp_str: string;
24
+ };
25
+ }
26
+ export interface DanmuChunk<ObjectType extends DanmuObject> {
27
+ objs: ObjectType[];
28
+ }
29
+ export interface DanmuCluster {
30
+ peers: DanmuObjectPeer[];
31
+ desc: string[];
32
+ chosen_str: string;
33
+ }
34
+ export interface DanmuClusterPtr {
35
+ peers_ptr: [int, string][];
36
+ desc: string[];
37
+ chosen_str: string;
38
+ danuni_count: int;
39
+ danuni_dans: DanmuObject[];
40
+ }
41
+ export interface DanmuClusterOutput {
42
+ clusters: DanmuClusterPtr[];
43
+ stats: Stats;
44
+ }
45
+ export declare class Stats {
46
+ combined_identical: number;
47
+ combined_edit_distance: number;
48
+ combined_pinyin_distance: number;
49
+ combined_cosine_distance: number;
50
+ deleted_blacklist: number;
51
+ deleted_blacklist_each: {
52
+ [k: string]: int;
53
+ };
54
+ ignored_whitelist: number;
55
+ ignored_type: number;
56
+ num_taolu_matched: number;
57
+ }
58
+ export declare class Queue<T> {
59
+ storage: {
60
+ [k: int]: T;
61
+ };
62
+ index_l: int;
63
+ index_r: int;
64
+ constructor(init?: T[]);
65
+ push(item: T): void;
66
+ pop(): void;
67
+ peek(): T | null;
68
+ size(): number;
69
+ [Symbol.iterator](): IterableIterator<T>;
70
+ }
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@dan-uni/dan-any-plugin-detaolu",
3
+ "version": "0.0.2",
4
+ "description": "A filter, dedupe and anti-spam plugin of dan-any, a danmaku transformer lib, based on pakku.js.",
5
+ "keywords": [
6
+ "bangumi",
7
+ "danmaku"
8
+ ],
9
+ "license": "GPL-3.0-or-later",
10
+ "homepage": "https://github.com/ani-uni/danuni/tree/master/packages/dan-any-plugin-detaolu#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/ani-uni/danuni/issues"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/ani-uni/danuni.git"
17
+ },
18
+ "author": "rinne",
19
+ "main": "dist/index.js",
20
+ "module": "dist/index.js",
21
+ "types": "dist/src/index.d.ts",
22
+ "browser": "dist/index.umd.min.js",
23
+ "scripts": {
24
+ "test": "vitest",
25
+ "test:ui": "vitest --ui",
26
+ "coverage": "vitest run --coverage",
27
+ "bench": "vitest bench",
28
+ "lint": "eslint",
29
+ "build": "rslib build",
30
+ "build:types": "tsc"
31
+ },
32
+ "dependencies": {
33
+ "@dan-uni/dan-any": "workspace:^",
34
+ "fs-extra": "^11.3.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/fs-extra": "^11.0.4"
38
+ }
39
+ }
@@ -0,0 +1,27 @@
1
+ import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill'
2
+ import { defineConfig } from '@rslib/core'
3
+
4
+ import pkg from './package.json'
5
+
6
+ export default defineConfig({
7
+ lib: [
8
+ {
9
+ format: 'esm',
10
+ output: {
11
+ filename: { js: 'index.js' },
12
+ target: 'node',
13
+ },
14
+ dts: true,
15
+ },
16
+ {
17
+ format: 'umd',
18
+ output: {
19
+ filename: { js: 'index.umd.min.js' },
20
+ target: 'web',
21
+ },
22
+ dts: true,
23
+ umdName: pkg.name,
24
+ plugins: [pluginNodePolyfill()],
25
+ },
26
+ ],
27
+ })
@@ -0,0 +1,39 @@
1
+ //基于以下注释,根据vitest生成测试用例
2
+ import { describe, it } from 'vitest'
3
+
4
+ import { UniPool } from '@dan-uni/dan-any'
5
+
6
+ import detaolu from '.'
7
+
8
+ const xml = `<i>
9
+ <chatserver>chat.bilibili.com</chatserver>
10
+ <chatid>1156756312</chatid>
11
+ <mission>0</mission>
12
+ <maxlimit>2947</maxlimit>
13
+ <state>0</state>
14
+ <real_name>0</real_name>
15
+ <source>k-v</source>
16
+ <d p="13.213,1,25,16777215,1686314041,3,ff41173d,1335658005672492032">喜欢</d>
17
+ <d p="13.213,1,25,16777215,1686590010,0,296b35b5,1337972999512832512">来了 哈哈~~</d>
18
+ <d p="13.246,1,25,16777215,1686276875,0,5664cfc4,1335346233459549696">就是</d>
19
+ <d p="13.266,1,25,16777215,1686283375,0,c7e6646f,1335400761013670912">什么鬼?</d>
20
+ <d p="13.284,1,25,16777215,1686291338,0,38662881,1335467554877267456">哇哦</d>
21
+ <d p="13.306,1,25,16777215,1686268410,0,4c01de10,1335275224983600896">试试</d>
22
+ <d p="13.331,1,25,16777215,1686948453,3,56a3c5d5,1340979831550069760">不喜欢</d>
23
+ <d p="13.374,1,25,16777215,1686300770,3,647fe355,1335546672880933888">不喜欢</d>
24
+ <d p="13.376,1,25,16777215,1686297921,0,469d94b8,1335522778300134400">哦豁</d>
25
+ <d p="13.419,1,25,8700107,1686268005,0,be402447,1335271828100244224">太酷啦</d>
26
+ <d p="13.419,1,25,16777215,1686316828,3,7ffb6619,1335681385016736768">喜欢</d>
27
+ <d p="13.459,1,25,16777215,1686299729,0,45834405,1335537942797634048">一般,不好看</d>
28
+ <d p="13.462,1,25,16777215,1686302133,0,3cab672c,1335558106620590080">哈哈哈</d>
29
+ <d p="13.481,1,25,16777215,1686297342,0,ce67fafd,1335517923728804864">?</d>
30
+ <d p="13.499,1,25,16777215,1686301548,3,2848bf1c,1335553202649003264">不喜欢</d>
31
+ </i>`
32
+
33
+ describe('其它', () => {
34
+ const pool = UniPool.fromBiliXML(xml)
35
+ it('反套路(基于pakku.js实现的弹幕去重)', async () => {
36
+ const d = (await pool.pipe(detaolu({ MAX_COSINE: 1000 }))).minify()
37
+ console.info(d)
38
+ })
39
+ })
package/src/index.ts ADDED
@@ -0,0 +1,70 @@
1
+ import type { Config as DeTaoLuConfig } from './pakku.js'
2
+
3
+ import { UniDM, UniDMTools, UniPool } from '@dan-uni/dan-any'
4
+
5
+ import pakkujs from './pakku.js'
6
+
7
+ async function detaolu(that: UniPool, config?: DeTaoLuConfig) {
8
+ const p = await pakkujs(
9
+ {
10
+ objs: that.dans.map((d) => ({
11
+ time_ms: d.progress * 1000,
12
+ mode: d.mode, //TODO
13
+ content: d.content,
14
+ pool: d.pool,
15
+ // danuni_sender: d.senderID,
16
+ danuni_dan: d,
17
+ })),
18
+ },
19
+ config,
20
+ )
21
+ const selected = p.clusters.map((p) => {
22
+ if (p.danuni_dans.length === 1) {
23
+ return p.danuni_dans[0].danuni_dan
24
+ } else {
25
+ const dans = p.danuni_dans,
26
+ pool = new UniPool(dans.map((d) => d.danuni_dan))
27
+ function isAllBottomMode(p: UniPool) {
28
+ return p.dans.every((d) => d.mode === UniDMTools.Modes.Bottom)
29
+ }
30
+ const progess = pool.dans.map((d) => d.progress)
31
+ return UniDM.create({
32
+ SOID: pool.shared.SOID ?? pool.dans[0].SOID,
33
+ progress: dans[0].danuni_dan.progress,
34
+ mode:
35
+ pool.shared.mode ??
36
+ (isAllBottomMode(pool)
37
+ ? UniDMTools.Modes.Bottom
38
+ : UniDMTools.Modes.Top),
39
+ fontsize: dans.length > 0 ? 36 : 25,
40
+ color: pool.shared.color ?? pool.most.color,
41
+ senderID: 'detaolu[bot]@dan-any',
42
+ content: p.chosen_str,
43
+ weight: 10,
44
+ pool: pool.shared.pool ?? pool.most.pool,
45
+ attr: ['Protect'],
46
+ platform: pool.shared.platform ?? pool.most.platform,
47
+ extra: {
48
+ danuni: {
49
+ merge: {
50
+ count: p.danuni_count,
51
+ duration: Math.max(...progess) - Math.min(...progess),
52
+ senders: pool.dans
53
+ .filter((d) => d.content === p.chosen_str)
54
+ .map((d) => d.senderID),
55
+ taolu_count: pool.dans.length,
56
+ taolu_senders: pool.dans.map((d) => d.senderID),
57
+ },
58
+ },
59
+ },
60
+ })
61
+ }
62
+ })
63
+ return new UniPool(selected)
64
+ }
65
+
66
+ function detaolu_constructor(config?: DeTaoLuConfig) {
67
+ return (that: UniPool) => detaolu(that, config)
68
+ }
69
+
70
+ export default detaolu_constructor