iMessage 구조
Macbook에 iphone iMessage를 동기화하면 ~/Users/Name/Library/Messages 폴더에 저장된다. 저장된 폴더를 보면 .db로 관리되는 것을 볼수있다. sqlite로 저장되며 다양한 컬럼들이 있다.
주요 테이블은 message로 text와 attributedBody에서 메세지 본문을 찾을 수 있다.
- **ROWID**: 각 행(row)의 고유 식별자.
- **guid**: 메시지의 전역 고유 식별자.
- **text**: 메시지의 내용.
- **replace**: 대체 텍스트.
- **service_center**: 메시지를 처리한 서비스 센터.
- **handle_id**: 메시지의 송신자 또는 수신자의 ID.
- **subject**: 메시지의 주제.
- **country**: 메시지가 발송된 국가.
- **attributedBody**: 속성이 부여된 메시지 본문.
- **version**: 메시지의 버전.
- **type**: 메시지 유형.
- **service**: 메시지가 전송된 서비스 (iMessage, SMS 등).
- **account**: 메시지를 보낸 계정.
- **account_guid**: 계정의 전역 고유 식별자.
- **error**: 메시지 전송 오류 여부.
- **date**: 메시지가 전송된 날짜.
- **date_read**: 메시지가 읽힌 날짜.
- **date_delivered**: 메시지가 전달된 날짜.
- **is_delivered**: 메시지가 전달되었는지 여부.
- **is_finished**: 메시지 전송이 완료되었는지 여부.
- **is_emote**: 이모티콘 메시지인지 여부.
- **is_from_me**: 메시지가 나에게서 보낸 것인지 여부.
- **is_empty**: 메시지 내용이 비어 있는지 여부.
- **is_delayed**: 메시지가 지연되었는지 여부.
- **is_auto_reply**: 자동 응답 메시지인지 여부.
- **is_prepared**: 메시지가 준비되었는지 여부.
- **is_read**: 메시지가 읽혔는지 여부.
- **is_system_message**: 시스템 메시지인지 여부.
- **is_sent**: 메시지가 발송되었는지 여부.
- **has_dd_results**: 데이터 탐지 결과가 있는지 여부.
- **is_service_message**: 서비스 메시지인지 여부.
- **is_forward**: 메시지가 전달되었는지 여부.
- **was_downgraded**: 메시지가 다운그레이드 되었는지 여부.
- **is_archive**: 메시지가 아카이브되었는지 여부.
- **cache_has_attachments**: 메시지에 첨부 파일이 있는지 여부.
- **cache_roomnames**: 캐시된 방 이름.
- **was_data_detected**: 데이터가 탐지되었는지 여부.
- **was_deduplicated**: 중복 제거되었는지 여부.
- **is_audio_message**: 오디오 메시지인지 여부.
- **is_played**: 메시지가 재생되었는지 여부.
- **date_played**: 메시지가 재생된 날짜.
- **item_type**: 항목 유형.
- **other_handle**: 다른 핸들.
- **group_title**: 그룹 제목.
- **group_action_type**: 그룹 작업 유형.
- **share_status**: 공유 상태.
- **share_direction**: 공유 방향.
- **is_expirable**: 만료되는지 여부.
- **expire_state**: 만료 상태.
- **message_action_type**: 메시지 작업 유형.
- **message_source**: 메시지 출처.
- **associated_message_guid**: 연관된 메시지의 전역 고유 식별자.
- **associated_message_type**: 연관된 메시지 유형.
- **balloon_bundle_id**: 풍선 번들 ID.
- **payload_data**: 페이로드 데이터.
- **expressive_send_style_id**: 표현식 전송 스타일 ID.
- **associated_message_range_location**: 연관된 메시지 범위 위치.
- **associated_message_range_length**: 연관된 메시지 범위 길이.
- **time_expressive_send_played**: 표현식 전송 재생 시간.
- **message_summary_info**: 메시지 요약 정보.
- **ck_sync_state**: 클라우드 키트 동기화 상태.
- **ck_record_id**: 클라우드 키트 레코드 ID.
- **ck_record_change_tag**: 클라우드 키트 레코드 변경 태그.
- **destination_caller_id**: 대상 발신자 ID.
- **is_corrupt**: 손상되었는지 여부.
- **reply_to_guid**: 회신할 메시지의 전역 고유 식별자.
- **sort_id**: 정렬 ID.
- **is_spam**: 스팸 메시지인지 여부.
- **has_unseen_mention**: 보지 않은 멘션이 있는지 여부.
- **thread_originator_guid**: 스레드 시작자의 전역 고유 식별자.
- **thread_originator_part**: 스레드 시작자의 부분.
- **syndication_ranges**: 배포 범위.
- **synced_syndication_ranges**: 동기화된 배포 범위.
- **was_delivered_quietly**: 조용히 전달되었는지 여부.
- **did_notify_recipient**: 수신자가 알림을 받았는지 여부.
- **date_retracted**: 철회된 날짜.
- **date_edited**: 편집된 날짜.
- **was_detonated**: 폭파되었는지 여부.
- **part_count**: 파트 수.
- **is_stewie**: 스튜이 상태인지 여부.
- **is_kt_verified**: KT 인증 여부.
- **is_sos**: 긴급 메시지인지 여부.
- **is_critical**: 중요 메시지인지 여부.
- **bia_reference_id**: BIA 참조 ID.
- **fallback_hash**: 폴백 해시.
- **date_uct**: UCT 날짜.
Python으로 데이터 불러오기
먼저 ~/Users/Name/Library/Messages에 접근하려면 접근 권한이 필요하다. 구동하려는 python의 실행환경에 맞춰
개인정보 보호 및 보안 > 전체 디스크 접근 권한에서 터미널과 Vscode를 활성화 시켜준다.
다음으로 python에서 sqlite로 Message db를 불러온다.
import sqlite3
import pandas as pd
path = "/Users/Name/Library/Messages/chat.db"
# substitute username with your username
conn = sqlite3.connect(path)
# connect to the database
cur = conn.cursor()
# get the names of the tables in the database
# get the 10 entries of the message table using pandas
messages = pd.read_sql_query("select * from message order by date desc limit 10", conn)
# messages['attributedBody']
# b'\x04\x0bstreamtyped\x81\xe8\x03\x84\x01@\x84
불러온 message를 보면 Web 발신으로 온 문자들 대부분이 encode 되어 있어 확인이 어렵다. attributedBody를 decode 해서 문자를 확인한다.
def decode_message(row):
msg_text = row['text']
msg_attributed_body = row['attributedBody']
# Logic from https://github.com/my-other-github-account/imessage_tools
body=''
if msg_text:
body = msg_text
elif msg_attributed_body is None:
body = ''
else:
try:
msg_attributed_body = msg_attributed_body.decode('utf-8', errors='replace')
except AttributeError as err:
pass
if "NSNumber" in str(msg_attributed_body):
msg_attributed_body = str(msg_attributed_body).split("NSNumber")[0]
if "NSString" in msg_attributed_body:
msg_attributed_body = str(msg_attributed_body).split("NSString")[1]
if "NSDictionary" in msg_attributed_body:
msg_attributed_body = str(msg_attributed_body).split("NSDictionary")[0]
msg_attributed_body = msg_attributed_body[6:-12]
body = msg_attributed_body
return body
print(decode_message(messages.iloc[0]))
# [Web발신]
# 네이버 현대카드 승인
# *
# 13,000원 일시불
# 06/15 13:49
# -----
# 누적108,108,128,328,108,420원
Mac과 Iphone을 같이 사용하는 사람은 위 몇줄 코드로 데이터를 불러와 LLM으로 여러가지를 할 수 있다. 다음 프로젝트로 ~
'Mac' 카테고리의 다른 글
Mac 실행 중인 프로세스 확인 하기 (1 ~ 75) (0) | 2024.05.31 |
---|---|
Mac 마우스 떨림 현상 고치기 (0) | 2024.05.12 |
[ERR_NGROK_108] ngrok error (0) | 2024.01.13 |
[M1 mac] ngrok 설치 오류 No such file or directory @ rb_file_s_rename - (0) | 2024.01.06 |
[Karabiner] Keyboard is ignored temporarily until key X is pressed #1848 (0) | 2023.10.08 |