chzzk-python 0.8.0__tar.gz → 0.9.0__tar.gz

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.
Files changed (120) hide show
  1. chzzk_python-0.9.0/.env.example +46 -0
  2. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/.github/workflows/ci.yml +2 -2
  3. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/.github/workflows/publish.yml +37 -3
  4. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/.gitignore +2 -0
  5. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/PKG-INFO +1 -1
  6. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/docs/unofficial-chat-websocket-protocol.md +170 -1
  7. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/_version.py +2 -2
  8. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/commands/chat.py +350 -116
  9. chzzk_python-0.9.0/src/chzzk/cli/formatter.py +382 -0
  10. chzzk_python-0.9.0/src/chzzk/cli/logging.py +48 -0
  11. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/main.py +57 -1
  12. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/apps/chat_interactive.py +15 -1
  13. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/apps/chat_viewer.py +13 -1
  14. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/widgets/chat.py +78 -23
  15. chzzk_python-0.9.0/src/chzzk/cli/writers.py +215 -0
  16. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/chat/client.py +54 -20
  17. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/chat/handler.py +10 -1
  18. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/chat/monitor.py +42 -8
  19. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/models/reconnect.py +1 -0
  20. chzzk_python-0.9.0/tests/cli/__init__.py +1 -0
  21. chzzk_python-0.9.0/tests/cli/test_formatter.py +565 -0
  22. chzzk_python-0.9.0/tests/cli/test_writers.py +325 -0
  23. chzzk_python-0.8.0/.github/workflows/release-please.yml +0 -15
  24. chzzk_python-0.8.0/src/chzzk/cli/logging.py +0 -24
  25. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/.python-version +0 -0
  26. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/CHANGELOG.md +0 -0
  27. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/LICENSE +0 -0
  28. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/README.md +0 -0
  29. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/README_KO.md +0 -0
  30. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/examples/.env.example +0 -0
  31. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/examples/oauth_server.py +0 -0
  32. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/examples/realtime_chat.py +0 -0
  33. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/examples/realtime_chat_async.py +0 -0
  34. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/examples/session_management.py +0 -0
  35. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/examples/unofficial_chat.py +0 -0
  36. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/examples/unofficial_chat_async.py +0 -0
  37. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/main.py +0 -0
  38. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/pyproject.toml +0 -0
  39. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/__init__.py +0 -0
  40. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/api/__init__.py +0 -0
  41. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/api/base.py +0 -0
  42. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/api/category.py +0 -0
  43. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/api/channel.py +0 -0
  44. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/api/chat.py +0 -0
  45. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/api/live.py +0 -0
  46. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/api/restriction.py +0 -0
  47. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/api/session.py +0 -0
  48. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/api/user.py +0 -0
  49. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/auth/__init__.py +0 -0
  50. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/auth/models.py +0 -0
  51. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/auth/oauth.py +0 -0
  52. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/auth/token.py +0 -0
  53. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/__init__.py +0 -0
  54. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/commands/__init__.py +0 -0
  55. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/commands/auth.py +0 -0
  56. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/commands/live.py +0 -0
  57. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/config.py +0 -0
  58. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/__init__.py +0 -0
  59. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/apps/__init__.py +0 -0
  60. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/apps/login.py +0 -0
  61. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/base.py +0 -0
  62. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/styles/app.tcss +0 -0
  63. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/utils.py +0 -0
  64. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/widgets/__init__.py +0 -0
  65. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/cli/tui/widgets/input.py +0 -0
  66. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/client.py +0 -0
  67. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/constants.py +0 -0
  68. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/exceptions/__init__.py +0 -0
  69. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/exceptions/errors.py +0 -0
  70. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/http/__init__.py +0 -0
  71. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/http/_base.py +0 -0
  72. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/http/client.py +0 -0
  73. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/http/endpoints.py +0 -0
  74. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/logging.py +0 -0
  75. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/models/__init__.py +0 -0
  76. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/models/category.py +0 -0
  77. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/models/channel.py +0 -0
  78. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/models/chat.py +0 -0
  79. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/models/common.py +0 -0
  80. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/models/live.py +0 -0
  81. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/models/restriction.py +0 -0
  82. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/models/session.py +0 -0
  83. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/models/user.py +0 -0
  84. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/py.typed +0 -0
  85. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/realtime/__init__.py +0 -0
  86. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/realtime/client.py +0 -0
  87. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/__init__.py +0 -0
  88. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/api/__init__.py +0 -0
  89. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/api/base.py +0 -0
  90. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/api/chat.py +0 -0
  91. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/api/live.py +0 -0
  92. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/api/user.py +0 -0
  93. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/auth/__init__.py +0 -0
  94. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/auth/cookie.py +0 -0
  95. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/chat/__init__.py +0 -0
  96. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/chat/connection.py +0 -0
  97. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/client.py +0 -0
  98. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/http/__init__.py +0 -0
  99. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/http/_base.py +0 -0
  100. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/http/client.py +0 -0
  101. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/http/endpoints.py +0 -0
  102. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/models/__init__.py +0 -0
  103. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/models/chat.py +0 -0
  104. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/models/live.py +0 -0
  105. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/src/chzzk/unofficial/models/user.py +0 -0
  106. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/__init__.py +0 -0
  107. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/api/__init__.py +0 -0
  108. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/api/test_category.py +0 -0
  109. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/api/test_channel.py +0 -0
  110. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/api/test_chat.py +0 -0
  111. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/api/test_live.py +0 -0
  112. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/api/test_restriction.py +0 -0
  113. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/api/test_session.py +0 -0
  114. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/api/test_user.py +0 -0
  115. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/auth/__init__.py +0 -0
  116. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/auth/test_oauth.py +0 -0
  117. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/realtime/__init__.py +0 -0
  118. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/realtime/test_client.py +0 -0
  119. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/tests/test_client.py +0 -0
  120. {chzzk_python-0.8.0 → chzzk_python-0.9.0}/uv.lock +0 -0
@@ -0,0 +1,46 @@
1
+ # Chzzk CLI Configuration
2
+ # Copy this file to .env and fill in your values
3
+
4
+ # Authentication (Naver Cookie)
5
+ # 브라우저에서 네이버 로그인 후 개발자 도구에서 쿠키 확인
6
+ # 1. 브라우저에서 chzzk.naver.com에 로그인
7
+ # 2. 개발자 도구 (F12) -> Application -> Cookies -> chzzk.naver.com
8
+ # 3. NID_AUT와 NID_SES 값을 복사
9
+ CHZZK_NID_AUT=
10
+ CHZZK_NID_SES=
11
+
12
+ # Logging Configuration
13
+ # Log level: DEBUG, INFO, WARNING, ERROR
14
+ CHZZK_LOG_LEVEL=WARNING
15
+
16
+ # Log file path (optional)
17
+ CHZZK_LOG_FILE=
18
+
19
+ # Disable console (stderr) logging output (set to 1 to disable)
20
+ CHZZK_NO_CONSOLE_LOG=
21
+
22
+ # Chat Format Configuration (Rich markup supported)
23
+ # Available variables: {time}, {server_time}, {badge}, {verified}, {role}, {name}, {msg}
24
+ # Example: "{time} {badge}{verified}{name}: {msg}"
25
+ CHZZK_CHAT_FORMAT=
26
+
27
+ # Donation Format (Rich markup supported)
28
+ # Available variables: {time}, {server_time}, {badge}, {verified}, {role}, {name}, {msg}, {amount}, {pay_type}, {donation_type}, {continuous_days}
29
+ # Example: "{time} {amount}원({pay_type}) {badge}{name}: {msg}"
30
+ CHZZK_DONATION_FORMAT=
31
+
32
+ # Sent Message Format (Rich markup supported)
33
+ # Available variables: {time}, {msg}
34
+ # Example: "{time} > {msg}"
35
+ CHZZK_SENT_FORMAT=
36
+
37
+ # Time format (strftime format string)
38
+ # Example: "%H:%M:%S" (24-hour), "%I:%M:%S %p" (12-hour with AM/PM)
39
+ CHZZK_TIME_FORMAT=
40
+
41
+ # Chat Output Configuration
42
+ # Save chat messages to file
43
+ CHZZK_CHAT_OUTPUT=
44
+
45
+ # Output format: jsonl, txt (default: jsonl)
46
+ CHZZK_CHAT_OUTPUT_FORMAT=
@@ -24,7 +24,7 @@ jobs:
24
24
  python-version: "3.12"
25
25
 
26
26
  - name: Install dependencies
27
- run: uv sync --dev
27
+ run: uv sync --dev --all-extras
28
28
 
29
29
  - name: Run ruff format check
30
30
  run: uv run ruff format --check .
@@ -53,7 +53,7 @@ jobs:
53
53
  python-version: ${{ matrix.python-version }}
54
54
 
55
55
  - name: Install dependencies
56
- run: uv sync --dev
56
+ run: uv sync --dev --all-extras
57
57
 
58
58
  - name: Run tests
59
59
  run: uv run pytest -v
@@ -1,8 +1,9 @@
1
1
  name: Publish to PyPI
2
2
 
3
3
  on:
4
- release:
5
- types: [published]
4
+ push:
5
+ tags:
6
+ - "v*"
6
7
  workflow_dispatch:
7
8
 
8
9
  jobs:
@@ -36,9 +37,42 @@ jobs:
36
37
  name: dist
37
38
  path: dist/
38
39
 
39
- publish-pypi:
40
+ release:
40
41
  needs: build
41
42
  runs-on: ubuntu-latest
43
+ if: startsWith(github.ref, 'refs/tags/v')
44
+ permissions:
45
+ contents: write
46
+ steps:
47
+ - uses: actions/checkout@v6
48
+ with:
49
+ fetch-depth: 0
50
+
51
+ - name: Generate changelog
52
+ uses: orhun/git-cliff-action@v4
53
+ with:
54
+ config: github
55
+ args: --latest --strip header
56
+ env:
57
+ OUTPUT: CHANGES.md
58
+ GITHUB_REPO: ${{ github.repository }}
59
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
60
+
61
+ - name: Download artifacts
62
+ uses: actions/download-artifact@v4
63
+ with:
64
+ name: dist
65
+ path: dist/
66
+
67
+ - name: Create Release
68
+ uses: softprops/action-gh-release@v2
69
+ with:
70
+ body_path: CHANGES.md
71
+ files: dist/*
72
+
73
+ publish-pypi:
74
+ needs: release
75
+ runs-on: ubuntu-latest
42
76
  environment:
43
77
  name: pypi
44
78
  url: https://pypi.org/p/chzzk-python
@@ -41,3 +41,5 @@ htmlcov/
41
41
  CLAUDE.md
42
42
  .claude/
43
43
 
44
+ *.log
45
+ *.txt
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chzzk-python
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Unofficial Python SDK for Chzzk (NAVER Live Streaming Platform) API
5
5
  Project-URL: Homepage, https://github.com/hypn4/chzzk-python
6
6
  Project-URL: Repository, https://github.com/hypn4/chzzk-python
@@ -1,6 +1,6 @@
1
1
  # Chzzk 비공식 채팅 WebSocket 프로토콜 분석
2
2
 
3
- > 최종 업데이트: 2026-01-23
3
+ > 최종 업데이트: 2026-01-25
4
4
  > 분석 방법: Chrome DevTools WebSocket 메시지 캡처
5
5
 
6
6
  ## 개요
@@ -255,6 +255,174 @@ GET https://api.chzzk.naver.com/service/v1/user/status
255
255
 
256
256
  ---
257
257
 
258
+ ## 수신 메시지 구조
259
+
260
+ ### 6. CHAT (cmd: 93101)
261
+
262
+ 실시간 채팅 메시지 수신.
263
+
264
+ ```json
265
+ {
266
+ "ver": "3",
267
+ "cmd": 93101,
268
+ "svcid": "game",
269
+ "cid": "N2FOy2",
270
+ "bdy": [
271
+ {
272
+ "svcid": "game",
273
+ "cid": "N2FOy2",
274
+ "mbrCnt": 1234,
275
+ "uid": "14f67c97d654f655afc0c9b3********",
276
+ "profile": "{\"userIdHash\":\"14f67c97...\",\"nickname\":\"닉네임\",\"profileImageUrl\":\"...\",\"userRoleCode\":\"common_user\",\"badge\":null,\"title\":null,\"verifiedMark\":false,\"activityBadges\":[{\"badgeNo\":123,\"badgeId\":\"구독자\",\"name\":\"구독자\",\"imageUrl\":\"...\"}],\"streamingProperty\":{}}",
277
+ "msg": "안녕하세요!",
278
+ "msgTypeCode": 1,
279
+ "msgStatusType": "NORMAL",
280
+ "extras": "{\"chatType\":\"STREAMING\",\"osType\":\"PC\",\"emojis\":{}}",
281
+ "ctime": 1769139665965,
282
+ "utime": 1769139665965,
283
+ "msgTime": 1769139665965
284
+ }
285
+ ]
286
+ }
287
+ ```
288
+
289
+ **bdy 배열 내 메시지 필드:**
290
+
291
+ | 필드 | 설명 |
292
+ |------|------|
293
+ | `uid` | 사용자 ID 해시 |
294
+ | `profile` | 사용자 프로필 (JSON 문자열, 아래 참조) |
295
+ | `msg` | 메시지 내용 |
296
+ | `msgTypeCode` | 메시지 타입 (`1` = 일반 텍스트, `10` = 후원 메시지) |
297
+ | `msgStatusType` | 메시지 상태 (`NORMAL`, `HIDDEN` 등) |
298
+ | `extras` | 추가 데이터 (JSON 문자열) |
299
+ | `ctime` | 생성 시간 (밀리초) |
300
+ | `msgTime` | 메시지 시간 (밀리초) |
301
+ | `mbrCnt` | 현재 시청자 수 |
302
+
303
+ ### 7. DONATION (cmd: 93102)
304
+
305
+ 후원 메시지 수신.
306
+
307
+ ```json
308
+ {
309
+ "ver": "3",
310
+ "cmd": 93102,
311
+ "svcid": "game",
312
+ "cid": "N2FOy2",
313
+ "bdy": [
314
+ {
315
+ "uid": "14f67c97d654f655afc0c9b3********",
316
+ "profile": "{...}",
317
+ "msg": "응원합니다!",
318
+ "msgTypeCode": 10,
319
+ "msgStatusType": "NORMAL",
320
+ "extras": "{\"payType\":\"CURRENCY\",\"payAmount\":1000,\"donationType\":\"CHAT\",...}",
321
+ "msgTime": 1769139665965
322
+ }
323
+ ]
324
+ }
325
+ ```
326
+
327
+ **중요**: 후원 관련 필드(`payType`, `payAmount`, `donationType`)는 **`extras` JSON 문자열 내부**에 있습니다. 최상위 필드가 아닙니다.
328
+
329
+ **extras 필드 파싱 후 전체 구조:**
330
+
331
+ ```json
332
+ {
333
+ "emojis": {},
334
+ "streamingChannelId": "a9b3377345a2a37e68a6072ba5e77fec",
335
+ "donationId": "6alUxGqGBsQvsGNE1eoa0lV9JGEBl",
336
+ "donationType": "CHAT",
337
+ "payType": "CURRENCY",
338
+ "payAmount": 1000,
339
+ "nickname": "닉네임",
340
+ "osType": "PC",
341
+ "chatType": "STREAMING",
342
+ "isAnonymous": false,
343
+ "continuousDonationDays": 1,
344
+ "weeklyRankList": [...],
345
+ "donationUserWeeklyRank": {...}
346
+ }
347
+ ```
348
+
349
+ **extras 필드 내 DONATION 전용 필드:**
350
+
351
+ | 필드 | 타입 | 설명 |
352
+ |------|------|------|
353
+ | `payType` | string | 결제 타입 (`CURRENCY` = 치즈, `CHEESE` 등) |
354
+ | `payAmount` | int | 결제 금액 (KRW, 정수) |
355
+ | `donationType` | string | 후원 타입 (`CHAT`, `VIDEO` 등) |
356
+ | `donationId` | string | 후원 고유 ID |
357
+ | `isAnonymous` | boolean | 익명 여부 |
358
+ | `nickname` | string | 후원자 닉네임 (extras 내에도 포함) |
359
+ | `continuousDonationDays` | int | 연속 후원 일수 |
360
+ | `weeklyRankList` | array | 주간 후원 랭킹 목록 (상위 10명) |
361
+ | `donationUserWeeklyRank` | object | 후원자의 주간 랭킹 정보 |
362
+
363
+ ---
364
+
365
+ ## profile 필드 구조
366
+
367
+ `profile` 필드는 JSON 문자열로 인코딩되어 있으며, 파싱 후 다음 구조를 가짐:
368
+
369
+ ```json
370
+ {
371
+ "userIdHash": "14f67c97d654f655afc0c9b3********",
372
+ "nickname": "닉네임",
373
+ "profileImageUrl": "https://...",
374
+ "userRoleCode": "common_user",
375
+ "badge": null,
376
+ "title": null,
377
+ "verifiedMark": false,
378
+ "activityBadges": [
379
+ {
380
+ "badgeNo": 1708498,
381
+ "badgeId": "donation_accumulate_amount_lv1",
382
+ "name": "치즈 후원자",
383
+ "imageUrl": "https://ssl.pstatic.net/static/nng/glive/icon/cheese01.png",
384
+ "activated": true
385
+ }
386
+ ],
387
+ "streamingProperty": {
388
+ "nicknameColor": {"colorCode": "CC000"},
389
+ "activatedAchievementBadgeIds": []
390
+ },
391
+ "viewerBadges": [
392
+ {
393
+ "type": "STANDARD",
394
+ "badge": {
395
+ "badgeId": "donation_accumulate_amount_lv1",
396
+ "scope": "CHANNEL",
397
+ "imageUrl": "https://ssl.pstatic.net/static/nng/glive/badge/recent_cheese01.png"
398
+ }
399
+ }
400
+ ]
401
+ }
402
+ ```
403
+
404
+ **주요 필드 설명:**
405
+
406
+ | 필드 | 타입 | 설명 |
407
+ |------|------|------|
408
+ | `userIdHash` | string | 사용자 ID 해시 |
409
+ | `nickname` | string | 닉네임 |
410
+ | `profileImageUrl` | string | 프로필 이미지 URL |
411
+ | `userRoleCode` | string | 권한 코드 (`common_user`, `streamer`, `manager` 등) |
412
+ | `badge` | object \| null | 대표 배지 (`name`, `imageUrl` 등) |
413
+ | `title` | object \| null | 칭호 (`name`, `color` 등) |
414
+ | `verifiedMark` | boolean | 인증 마크 여부 |
415
+ | `activityBadges` | array | 활동 배지 목록 (구독, 후원 레벨 등) |
416
+ | `streamingProperty` | object | 스트리밍 속성 (닉네임 색상 등) |
417
+ | `viewerBadges` | array | 시청자 배지 목록 (채널별/글로벌 배지) |
418
+
419
+ **참고**: `badge`와 `activityBadges`는 서로 다른 필드입니다:
420
+ - `badge`: 단일 대표 배지 (스트리머가 지정한 배지, 대부분 null)
421
+ - `activityBadges`: 활동 기반 배지 목록 (구독자, 후원 레벨 등)
422
+ - `viewerBadges`: 시청자 배지 (채널/글로벌 스코프)
423
+
424
+ ---
425
+
258
426
  ## 주의사항
259
427
 
260
428
  1. **프로토콜 버전**: 모든 메시지에 `"ver": "3"` 사용
@@ -269,4 +437,5 @@ GET https://api.chzzk.naver.com/service/v1/user/status
269
437
 
270
438
  | 날짜 | 변경 내용 |
271
439
  |------|----------|
440
+ | 2026-01-25 | CHAT/DONATION 메시지 구조 추가, profile 필드 상세 문서화 |
272
441
  | 2026-01-23 | 최초 작성. Chrome DevTools WebSocket 캡처 기반 프로토콜 분석 |
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.8.0'
32
- __version_tuple__ = version_tuple = (0, 8, 0)
31
+ __version__ = version = '0.9.0'
32
+ __version_tuple__ = version_tuple = (0, 9, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None