chzzk-python 0.14.0__tar.gz → 0.14.2__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 (117) hide show
  1. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/PKG-INFO +1 -1
  2. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/examples/oauth_server.py +2 -1
  3. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/examples/unofficial_chat.py +1 -1
  4. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/examples/unofficial_chat_async.py +1 -1
  5. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/_version.py +2 -2
  6. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/commands/chat.py +144 -2
  7. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/.dockerignore +0 -0
  8. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/.env.example +0 -0
  9. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/.github/workflows/build.yml +0 -0
  10. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/.github/workflows/ci.yml +0 -0
  11. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/.github/workflows/docker.yml +0 -0
  12. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/.github/workflows/publish.yml +0 -0
  13. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/.gitignore +0 -0
  14. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/.python-version +0 -0
  15. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/Dockerfile +0 -0
  16. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/LICENSE +0 -0
  17. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/README.md +0 -0
  18. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/README_KO.md +0 -0
  19. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/chzzk.spec +0 -0
  20. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/docker-compose.yml +0 -0
  21. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/docs/unofficial-chat-websocket-protocol.md +0 -0
  22. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/examples/.env.example +0 -0
  23. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/examples/realtime_chat.py +0 -0
  24. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/examples/realtime_chat_async.py +0 -0
  25. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/examples/session_management.py +0 -0
  26. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/main.py +0 -0
  27. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/pyproject.toml +0 -0
  28. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/scripts/build.py +0 -0
  29. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/__init__.py +0 -0
  30. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/api/__init__.py +0 -0
  31. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/api/base.py +0 -0
  32. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/api/category.py +0 -0
  33. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/api/channel.py +0 -0
  34. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/api/chat.py +0 -0
  35. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/api/live.py +0 -0
  36. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/api/restriction.py +0 -0
  37. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/api/session.py +0 -0
  38. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/api/user.py +0 -0
  39. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/auth/__init__.py +0 -0
  40. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/auth/models.py +0 -0
  41. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/auth/oauth.py +0 -0
  42. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/auth/token.py +0 -0
  43. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/__init__.py +0 -0
  44. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/commands/__init__.py +0 -0
  45. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/commands/auth.py +0 -0
  46. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/commands/live.py +0 -0
  47. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/config.py +0 -0
  48. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/formatter.py +0 -0
  49. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/logging.py +0 -0
  50. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/main.py +0 -0
  51. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/timezone.py +0 -0
  52. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/cli/writers.py +0 -0
  53. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/client.py +0 -0
  54. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/constants.py +0 -0
  55. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/exceptions/__init__.py +0 -0
  56. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/exceptions/errors.py +0 -0
  57. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/http/__init__.py +0 -0
  58. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/http/_base.py +0 -0
  59. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/http/client.py +0 -0
  60. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/http/endpoints.py +0 -0
  61. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/logging.py +0 -0
  62. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/models/__init__.py +0 -0
  63. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/models/category.py +0 -0
  64. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/models/channel.py +0 -0
  65. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/models/chat.py +0 -0
  66. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/models/common.py +0 -0
  67. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/models/live.py +0 -0
  68. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/models/restriction.py +0 -0
  69. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/models/session.py +0 -0
  70. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/models/user.py +0 -0
  71. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/py.typed +0 -0
  72. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/realtime/__init__.py +0 -0
  73. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/realtime/client.py +0 -0
  74. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/__init__.py +0 -0
  75. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/api/__init__.py +0 -0
  76. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/api/base.py +0 -0
  77. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/api/chat.py +0 -0
  78. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/api/live.py +0 -0
  79. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/api/user.py +0 -0
  80. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/auth/__init__.py +0 -0
  81. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/auth/cookie.py +0 -0
  82. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/chat/__init__.py +0 -0
  83. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/chat/client.py +0 -0
  84. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/chat/connection.py +0 -0
  85. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/chat/handler.py +0 -0
  86. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/chat/monitor.py +0 -0
  87. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/client.py +0 -0
  88. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/http/__init__.py +0 -0
  89. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/http/_base.py +0 -0
  90. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/http/client.py +0 -0
  91. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/http/endpoints.py +0 -0
  92. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/models/__init__.py +0 -0
  93. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/models/chat.py +0 -0
  94. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/models/live.py +0 -0
  95. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/models/reconnect.py +0 -0
  96. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/src/chzzk/unofficial/models/user.py +0 -0
  97. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/__init__.py +0 -0
  98. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/api/__init__.py +0 -0
  99. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/api/test_category.py +0 -0
  100. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/api/test_channel.py +0 -0
  101. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/api/test_chat.py +0 -0
  102. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/api/test_live.py +0 -0
  103. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/api/test_restriction.py +0 -0
  104. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/api/test_session.py +0 -0
  105. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/api/test_user.py +0 -0
  106. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/auth/__init__.py +0 -0
  107. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/auth/test_oauth.py +0 -0
  108. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/cli/__init__.py +0 -0
  109. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/cli/test_formatter.py +0 -0
  110. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/cli/test_writers.py +0 -0
  111. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/realtime/__init__.py +0 -0
  112. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/realtime/test_client.py +0 -0
  113. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/test_client.py +0 -0
  114. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/unofficial/__init__.py +0 -0
  115. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/unofficial/test_client.py +0 -0
  116. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/tests/unofficial/test_monitor.py +0 -0
  117. {chzzk_python-0.14.0 → chzzk_python-0.14.2}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chzzk-python
3
- Version: 0.14.0
3
+ Version: 0.14.2
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
@@ -16,6 +16,7 @@ from pathlib import Path
16
16
 
17
17
  from dotenv import load_dotenv
18
18
  from flask import Flask, redirect, request
19
+ from werkzeug.wrappers import Response
19
20
 
20
21
  from chzzk import (
21
22
  ChzzkAPIError,
@@ -115,7 +116,7 @@ def index() -> str:
115
116
 
116
117
 
117
118
  @app.route("/login")
118
- def login() -> object:
119
+ def login() -> Response:
119
120
  """Redirect to Chzzk authorization page."""
120
121
  auth_url, state = client.get_authorization_url()
121
122
  print(f"Generated state: {state}")
@@ -73,7 +73,7 @@ def main() -> None:
73
73
  @chat.on_donation
74
74
  def on_donation(msg: DonationMessage) -> None:
75
75
  """Handle incoming donations."""
76
- print(f"[Donation] {msg.nickname} donated {msg.pay_amount}won: {msg.message}")
76
+ print(f"[Donation] {msg.nickname} donated {msg.pay_amount}won: {msg.content}")
77
77
 
78
78
  @chat.on_system
79
79
  def on_system(data: dict) -> None:
@@ -72,7 +72,7 @@ async def main() -> None:
72
72
  @chat.on_donation
73
73
  async def on_donation(msg: DonationMessage) -> None:
74
74
  """Handle incoming donations."""
75
- print(f"[Donation] {msg.nickname} donated {msg.pay_amount}won: {msg.message}")
75
+ print(f"[Donation] {msg.nickname} donated {msg.pay_amount}won: {msg.content}")
76
76
 
77
77
  @chat.on_system
78
78
  async def on_system(data: dict) -> None:
@@ -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.14.0'
32
- __version_tuple__ = version_tuple = (0, 14, 0)
31
+ __version__ = version = '0.14.2'
32
+ __version_tuple__ = version_tuple = (0, 14, 2)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -254,7 +254,7 @@ def _run_watch_console(
254
254
  nonlocal writer, output_dir_writer, current_live_id
255
255
 
256
256
  # Rotate log file when live_id changes in output_dir mode
257
- if output_dir and event.live_id != current_live_id:
257
+ if output_dir and event.live_id is not None and event.live_id != current_live_id:
258
258
  try:
259
259
  open_date: str | None = None
260
260
  try:
@@ -310,6 +310,40 @@ def _run_watch_console(
310
310
 
311
311
  @chat.on_offline
312
312
  async def handle_offline(event: StatusChangeEvent) -> None:
313
+ nonlocal writer, output_dir_writer, current_live_id
314
+
315
+ # Rotate log file to offline file when stream ends
316
+ if output_dir and current_live_id is not None:
317
+ try:
318
+ new_writer, new_path = rotate_writer(
319
+ old_writer=output_dir_writer,
320
+ output_dir=output_dir,
321
+ channel_id=channel_id,
322
+ new_live_id=None,
323
+ open_date=None,
324
+ output_format=output_format,
325
+ )
326
+ output_dir_writer = new_writer
327
+ writer = new_writer
328
+ current_live_id = None
329
+
330
+ if json_output:
331
+ console.print(
332
+ json.dumps(
333
+ {
334
+ "event": "log_rotated",
335
+ "new_file": str(new_path),
336
+ "live_id": None,
337
+ }
338
+ )
339
+ )
340
+ else:
341
+ console.print(f"[dim]Log rotated: {new_path}[/dim]")
342
+ except OSError as e:
343
+ logger.warning(f"Failed to rotate log file on offline: {e}")
344
+ if not json_output:
345
+ console.print(f"[yellow]Warning:[/yellow] Log rotation failed: {e}")
346
+
313
347
  if json_output:
314
348
  console.print(
315
349
  json.dumps(
@@ -328,6 +362,43 @@ def _run_watch_console(
328
362
 
329
363
  @chat.on_reconnect
330
364
  async def handle_reconnect(event: ReconnectEvent) -> None:
365
+ nonlocal writer, output_dir_writer, current_live_id
366
+
367
+ # Compensate for on_live rotation miss (e.g. live_id was None at status change)
368
+ if output_dir and event.reason == ReconnectReason.STREAM_RESTARTED:
369
+ try:
370
+ new_live_detail = await client.live.get_live_detail(channel_id)
371
+ if (
372
+ new_live_detail.live_id is not None
373
+ and new_live_detail.live_id != current_live_id
374
+ ):
375
+ new_writer, new_path = rotate_writer(
376
+ old_writer=output_dir_writer,
377
+ output_dir=output_dir,
378
+ channel_id=channel_id,
379
+ new_live_id=new_live_detail.live_id,
380
+ open_date=new_live_detail.open_date,
381
+ output_format=output_format,
382
+ )
383
+ output_dir_writer = new_writer
384
+ writer = new_writer
385
+ current_live_id = new_live_detail.live_id
386
+
387
+ if json_output:
388
+ console.print(
389
+ json.dumps(
390
+ {
391
+ "event": "log_rotated",
392
+ "new_file": str(new_path),
393
+ "live_id": new_live_detail.live_id,
394
+ }
395
+ )
396
+ )
397
+ else:
398
+ console.print(f"[dim]Log rotated: {new_path}[/dim]")
399
+ except Exception:
400
+ logger.warning("Failed to rotate log on reconnect")
401
+
331
402
  if json_output:
332
403
  console.print(
333
404
  json.dumps(
@@ -735,7 +806,7 @@ def _run_interactive_chat_console(
735
806
  nonlocal writer, output_dir_writer, current_live_id
736
807
 
737
808
  # Rotate log file when live_id changes in output_dir mode
738
- if output_dir and event.live_id != current_live_id:
809
+ if output_dir and event.live_id is not None and event.live_id != current_live_id:
739
810
  try:
740
811
  open_date: str | None = None
741
812
  try:
@@ -791,6 +862,40 @@ def _run_interactive_chat_console(
791
862
 
792
863
  @chat.on_offline
793
864
  async def handle_offline(event: StatusChangeEvent) -> None:
865
+ nonlocal writer, output_dir_writer, current_live_id
866
+
867
+ # Rotate log file to offline file when stream ends
868
+ if output_dir and current_live_id is not None:
869
+ try:
870
+ new_writer, new_path = rotate_writer(
871
+ old_writer=output_dir_writer,
872
+ output_dir=output_dir,
873
+ channel_id=channel_id,
874
+ new_live_id=None,
875
+ open_date=None,
876
+ output_format=output_format,
877
+ )
878
+ output_dir_writer = new_writer
879
+ writer = new_writer
880
+ current_live_id = None
881
+
882
+ if json_output:
883
+ console.print(
884
+ json.dumps(
885
+ {
886
+ "event": "log_rotated",
887
+ "new_file": str(new_path),
888
+ "live_id": None,
889
+ }
890
+ )
891
+ )
892
+ else:
893
+ console.print(f"[dim]Log rotated: {new_path}[/dim]")
894
+ except OSError as e:
895
+ logger.warning(f"Failed to rotate log file on offline: {e}")
896
+ if not json_output:
897
+ console.print(f"[yellow]Warning:[/yellow] Log rotation failed: {e}")
898
+
794
899
  if json_output:
795
900
  console.print(
796
901
  json.dumps(
@@ -809,6 +914,43 @@ def _run_interactive_chat_console(
809
914
 
810
915
  @chat.on_reconnect
811
916
  async def handle_reconnect(event: ReconnectEvent) -> None:
917
+ nonlocal writer, output_dir_writer, current_live_id
918
+
919
+ # Compensate for on_live rotation miss (e.g. live_id was None at status change)
920
+ if output_dir and event.reason == ReconnectReason.STREAM_RESTARTED:
921
+ try:
922
+ new_live_detail = await client.live.get_live_detail(channel_id)
923
+ if (
924
+ new_live_detail.live_id is not None
925
+ and new_live_detail.live_id != current_live_id
926
+ ):
927
+ new_writer, new_path = rotate_writer(
928
+ old_writer=output_dir_writer,
929
+ output_dir=output_dir,
930
+ channel_id=channel_id,
931
+ new_live_id=new_live_detail.live_id,
932
+ open_date=new_live_detail.open_date,
933
+ output_format=output_format,
934
+ )
935
+ output_dir_writer = new_writer
936
+ writer = new_writer
937
+ current_live_id = new_live_detail.live_id
938
+
939
+ if json_output:
940
+ console.print(
941
+ json.dumps(
942
+ {
943
+ "event": "log_rotated",
944
+ "new_file": str(new_path),
945
+ "live_id": new_live_detail.live_id,
946
+ }
947
+ )
948
+ )
949
+ else:
950
+ console.print(f"[dim]Log rotated: {new_path}[/dim]")
951
+ except Exception:
952
+ logger.warning("Failed to rotate log on reconnect")
953
+
812
954
  if json_output:
813
955
  console.print(
814
956
  json.dumps(
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes