Skip to content

Commit 1114e46

Browse files
author
ComputelessComputer
committed
fix: preserve KakaoTalk conversation context
- treat generic and numeric KakaoTalk titles as fallback candidates so chat names can be recovered from visible text - strip KakaoTalk sidebar, profile, unread, and timestamp chrome while keeping participant names and message snippets - add regression coverage for generic, numeric, and chat-detail KakaoTalk captures
1 parent 0a2eb53 commit 1114e46

2 files changed

Lines changed: 138 additions & 0 deletions

File tree

Sources/OpenbirdKit/Capture/SnapshotSanitizer.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ struct SnapshotSanitizer {
3131
switch bundleId {
3232
case "com.tinyspeck.slackmacgap":
3333
return normalizedSlackTitle(trimmed)
34+
case "com.kakao.KakaoTalkMac":
35+
return normalizedKakaoTalkTitle(trimmed)
3436
default:
3537
return trimmed
3638
}
@@ -98,6 +100,17 @@ struct SnapshotSanitizer {
98100
|| normalized.contains("thread")
99101
}
100102

103+
private func normalizedKakaoTalkTitle(_ title: String) -> String {
104+
let normalized = title.normalizedComparisonKey
105+
if normalized.isEmpty {
106+
return ""
107+
}
108+
if normalized.allSatisfy({ $0.isNumber || $0 == " " }) {
109+
return ""
110+
}
111+
return title
112+
}
113+
101114
private func isGenericTitle(_ title: String, appName: String) -> Bool {
102115
title.isEmpty || title.normalizedComparisonKey == appName.normalizedComparisonKey
103116
}
@@ -142,12 +155,40 @@ struct SnapshotSanitizer {
142155
}
143156
}
144157

158+
if bundleId == "com.kakao.KakaoTalkMac" {
159+
if kakaoTalkChromeLines.contains(normalized) {
160+
return true
161+
}
162+
if normalized.contains("new message") || normalized.contains("new messages") {
163+
return true
164+
}
165+
if normalized.contains("chatrooms") {
166+
return true
167+
}
168+
if normalized.allSatisfy({ $0.isNumber || $0 == " " }) {
169+
return true
170+
}
171+
if isTimeLikeLine(normalized) {
172+
return true
173+
}
174+
}
175+
145176
if bundleId == "com.tinyspeck.slackmacgap" && normalized == "slack" {
146177
return true
147178
}
148179

149180
return false
150181
}
182+
183+
private func isTimeLikeLine(_ normalized: String) -> Bool {
184+
let words = normalized.split(separator: " ")
185+
guard words.isEmpty == false else { return true }
186+
187+
let dateTokens = Set(["am", "pm", "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "sept", "oct", "nov", "dec"])
188+
return words.allSatisfy { word in
189+
word.allSatisfy(\.isNumber) || dateTokens.contains(String(word))
190+
}
191+
}
151192
}
152193

153194
private extension Array where Element == String {
@@ -176,3 +217,23 @@ private let messageChromeLines: Set<String> = [
176217
"search",
177218
"start facetime",
178219
]
220+
221+
private let kakaoTalkChromeLines: Set<String> = [
222+
"add chatroom",
223+
"all folder",
224+
"button",
225+
"chatlist icon notioff",
226+
"chatroom folder",
227+
"chats",
228+
"common icon newdot",
229+
"common icon triangledown",
230+
"emoticon",
231+
"enter a message",
232+
"kakaotalk",
233+
"notifications",
234+
"profile",
235+
"search",
236+
"settings",
237+
"silent chatroom",
238+
"unread folder",
239+
]

Tests/OpenbirdKitTests/SnapshotSanitizerTests.swift

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,83 @@ struct SnapshotSanitizerTests {
102102
#expect(sanitized.visibleText == "Can you review this before 5?\nYep, I'll take a look.")
103103
}
104104

105+
@Test func filtersKakaoTalkChromeAndKeepsMessageText() {
106+
let sanitizer = SnapshotSanitizer()
107+
let snapshot = WindowSnapshot(
108+
bundleId: "com.kakao.KakaoTalkMac",
109+
appName: "KakaoTalk",
110+
windowTitle: "Yoo✨",
111+
url: nil,
112+
visibleText: """
113+
Yoo✨
114+
Profile
115+
6:29 PM
116+
오 저도 사나 좋아하는데...
117+
Enter a message
118+
""",
119+
source: "accessibility"
120+
)
121+
122+
let sanitized = sanitizer.sanitize(snapshot)
123+
124+
#expect(sanitized.windowTitle == "Yoo✨")
125+
#expect(sanitized.visibleText == "오 저도 사나 좋아하는데...")
126+
}
127+
128+
@Test func fallsBackToKakaoTalkConversationWhenTitleIsGeneric() {
129+
let sanitizer = SnapshotSanitizer()
130+
let snapshot = WindowSnapshot(
131+
bundleId: "com.kakao.KakaoTalkMac",
132+
appName: "KakaoTalk",
133+
windowTitle: "KakaoTalk",
134+
url: nil,
135+
visibleText: """
136+
KakaoTalk
137+
common icon newdot
138+
Notifications
139+
Settings
140+
Chats
141+
Add chatroom
142+
Search
143+
Profile
144+
8:59 PM
145+
박륜지
146+
내가 강한 사람이라서 스스로 처리한거지^
147+
""",
148+
source: "accessibility"
149+
)
150+
151+
let sanitized = sanitizer.sanitize(snapshot)
152+
153+
#expect(sanitized.windowTitle == "박륜지")
154+
#expect(sanitized.visibleText == "내가 강한 사람이라서 스스로 처리한거지^")
155+
}
156+
157+
@Test func fallsBackToKakaoTalkConversationWhenTitleIsNumeric() {
158+
let sanitizer = SnapshotSanitizer()
159+
let snapshot = WindowSnapshot(
160+
bundleId: "com.kakao.KakaoTalkMac",
161+
appName: "KakaoTalk",
162+
windowTitle: "1",
163+
url: nil,
164+
visibleText: """
165+
Chats
166+
Silent Chatroom
167+
박륜지
168+
Unread folder, 1 New message
169+
8:30 PM
170+
ㅋㅋㅋㅋ 먼지가 없긴 해요
171+
Enter a message
172+
""",
173+
source: "accessibility"
174+
)
175+
176+
let sanitized = sanitizer.sanitize(snapshot)
177+
178+
#expect(sanitized.windowTitle == "박륜지")
179+
#expect(sanitized.visibleText == "ㅋㅋㅋㅋ 먼지가 없긴 해요")
180+
}
181+
105182
@Test func fallsBackToMeaningfulVisibleTextWhenWindowTitleIsMissing() {
106183
let sanitizer = SnapshotSanitizer()
107184
let snapshot = WindowSnapshot(

0 commit comments

Comments
 (0)