/
mod.ts
126 lines (107 loc) · 2.85 KB
/
mod.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
const regexp = {
date: /^\d{4}[\/\.]\d{1,2}[\/\.]\d{1,2}/,
time: /\d{1,2}:\d{1,2}/,
talk: /^(.*\d{1,2}:\d{1,2})[ \t](.*?)[ \t](.*)/,
};
/* トークデータ */
export type TalkData = {
date: string;
time: string;
user: string;
message: string;
};
function isMessage(text: string): boolean {
text = text.trim();
if (text === "") return false;
const ignoreList = [
/^\[LINE\].+とのトーク履歴/,
/^\[.+\]$/,
/通話時間 \d{1,2}:\d{1,2}/,
/通話をキャンセルしました$/,
/不在着信$/,
/^.+がメッセージの送信を取り消しました$/,
/.+を作成しました$/,
/^イベント.+が.{2}されました/,
/アルバムを.{2}しました/,
/ノート[をに].{2}しました/,
/アルバムに写真を追加しました/,
/^\(emoji\)/,
/https?:\/\//,
];
for (const ignore of ignoreList) {
if (ignore.test(text)) return false;
}
return true;
}
function to24Hour(time: string): string {
const t = time.match(regexp.time)?.toString();
if (!t) return "";
return t
.split(":")
.map((e, i) => {
let n = parseInt(e.trim());
// 午後表記かつ、時間なら12を足して24時間表記にする
if (i === 0 && /^午後/.test(time)) {
n += 12;
}
return String(n).padStart(2, "0");
})
.join(":");
}
function fmtDate(date: string): string {
const d = date.match(regexp.date)?.toString();
if (!d) return "";
return d.split(/[\/\.]/).map((e, i) => {
// 年
if (i === 0) return e;
// 月日
return e.padStart(2, "0");
}).join("/");
}
/**
* LINEトーク履歴をパース
* @param text トーク履歴文字列
* @return トークデータ配列
*/
export function parse(text: string): TalkData[] {
const lines = text.split(/[\r\n]/).filter((e) => e !== "");
const results: TalkData[] = [];
let date = "";
let time = "";
let user = "";
let message = "";
for (const line of lines) {
// 日付を抽出
if (regexp.date.test(line)) {
date = fmtDate(line);
continue;
}
// トークを分割
const splited = line.match(regexp.talk)?.map((e) => e.trim());
if (splited) {
if (isMessage(message)) {
results.push({
date,
time,
user,
message: message.replace(/(^\"|\"$)/g, ""), // ダブルクオートを削除
});
}
time = to24Hour(splited[1]);
user = splited[2].replace(/\t.*$/g, ""); // 引用元の名前を削除
message = splited[3];
} else if (!regexp.time.test(line)) {
// 複数行をまとめる
message += ` ${line}`;
}
}
return results;
}
/**
* LINEトーク履歴をJSON文字列に変換
* @param text トーク履歴文字列
* @return JSON文字列
*/
export function toJson(text: string) {
return JSON.stringify(parse(text), null, "\t");
}