sticker-convert 2.8.2__tar.gz → 2.8.4__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. {sticker-convert-2.8.2/src/sticker_convert.egg-info → sticker_convert-2.8.4}/PKG-INFO +6 -6
  2. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/requirements.txt +5 -5
  3. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/converter.py +91 -43
  4. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/downloaders/download_signal.py +7 -7
  5. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/uploaders/compress_wastickers.py +3 -3
  6. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/uploaders/upload_signal.py +10 -10
  7. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/uploaders/upload_telegram.py +91 -65
  8. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/auth/get_line_auth.py +15 -21
  9. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/files/metadata_handler.py +5 -0
  10. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/version.py +1 -1
  11. {sticker-convert-2.8.2 → sticker_convert-2.8.4/src/sticker_convert.egg-info}/PKG-INFO +6 -6
  12. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert.egg-info/requires.txt +5 -5
  13. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/LICENSE +0 -0
  14. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/MANIFEST.in +0 -0
  15. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/README.md +0 -0
  16. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/pyproject.toml +0 -0
  17. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/setup.cfg +0 -0
  18. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/__init__.py +0 -0
  19. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/__main__.py +0 -0
  20. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/cli.py +0 -0
  21. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/definitions.py +0 -0
  22. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/downloaders/__init__.py +0 -0
  23. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/downloaders/download_base.py +0 -0
  24. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/downloaders/download_kakao.py +0 -0
  25. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/downloaders/download_line.py +0 -0
  26. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/downloaders/download_telegram.py +0 -0
  27. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui.py +0 -0
  28. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/__init__.py +0 -0
  29. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/frames/__init__.py +0 -0
  30. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/frames/comp_frame.py +0 -0
  31. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/frames/config_frame.py +0 -0
  32. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/frames/control_frame.py +0 -0
  33. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/frames/cred_frame.py +0 -0
  34. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/frames/input_frame.py +0 -0
  35. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/frames/output_frame.py +0 -0
  36. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/frames/progress_frame.py +0 -0
  37. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/frames/right_clicker.py +0 -0
  38. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/gui_utils.py +0 -0
  39. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/windows/__init__.py +0 -0
  40. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/windows/advanced_compression_window.py +0 -0
  41. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/windows/base_window.py +0 -0
  42. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/windows/kakao_get_auth_window.py +0 -0
  43. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/windows/line_get_auth_window.py +0 -0
  44. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/gui_components/windows/signal_get_auth_window.py +0 -0
  45. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/.github/FUNDING.yml +0 -0
  46. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/.gitignore +0 -0
  47. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/README.md +0 -0
  48. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers/Info.plist +0 -0
  49. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Info.plist +0 -0
  50. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Contents.json +0 -0
  51. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json +0 -0
  52. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Contents.json +0 -0
  53. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Sticker 1.png +0 -0
  54. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Contents.json +0 -0
  55. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Sticker 2.png +0 -0
  56. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Contents.json +0 -0
  57. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Sticker 3.png +0 -0
  58. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/App-Store-1024x1024pt.png +0 -0
  59. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json +0 -0
  60. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-App-Store-1024x768pt.png +0 -0
  61. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-67x50pt@2x.png +0 -0
  62. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-Pro-74x55pt@2x.png +0 -0
  63. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@2x.png +0 -0
  64. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@3x.png +0 -0
  65. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@2x.png +0 -0
  66. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@3x.png +0 -0
  67. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@2x.png +0 -0
  68. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@3x.png +0 -0
  69. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPad-Settings-29pt@2x.png +0 -0
  70. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-Settings-29pt@3x.png +0 -0
  71. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-settings-29pt@2x.png +0 -0
  72. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.pbxproj +0 -0
  73. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  74. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -0
  75. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcuserdata/niklaspeterson.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  76. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/ios-message-stickers-template/stickers.xcodeproj/xcuserdata/niklaspeterson.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  77. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/job.py +0 -0
  78. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/job_option.py +0 -0
  79. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/resources/NotoColorEmoji.ttf +0 -0
  80. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/resources/appicon.icns +0 -0
  81. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/resources/appicon.ico +0 -0
  82. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/resources/appicon.png +0 -0
  83. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/resources/compression.json +0 -0
  84. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/resources/emoji.json +0 -0
  85. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/resources/help.json +0 -0
  86. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/resources/input.json +0 -0
  87. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/resources/output.json +0 -0
  88. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/uploaders/__init__.py +0 -0
  89. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/uploaders/upload_base.py +0 -0
  90. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/uploaders/xcode_imessage.py +0 -0
  91. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/auth/get_kakao_auth.py +0 -0
  92. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/auth/get_signal_auth.py +0 -0
  93. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/callback.py +0 -0
  94. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/files/cache_store.py +0 -0
  95. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/files/json_manager.py +0 -0
  96. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/files/json_resources_loader.py +0 -0
  97. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/files/run_bin.py +0 -0
  98. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/files/sanitize_filename.py +0 -0
  99. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/media/apple_png_normalize.py +0 -0
  100. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/media/codec_info.py +0 -0
  101. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/media/decrypt_kakao.py +0 -0
  102. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/media/format_verify.py +0 -0
  103. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert/utils/url_detect.py +0 -0
  104. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert.egg-info/SOURCES.txt +0 -0
  105. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert.egg-info/dependency_links.txt +0 -0
  106. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert.egg-info/entry_points.txt +0 -0
  107. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/src/sticker_convert.egg-info/top_level.txt +0 -0
  108. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/tests/test_compression.py +0 -0
  109. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/tests/test_download.py +0 -0
  110. {sticker-convert-2.8.2 → sticker_convert-2.8.4}/tests/test_export.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.8.2
3
+ Version: 2.8.4
4
4
  Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, iMessage. Written in Python.
5
5
  Author-email: laggykiller <chaudominic2@gmail.com>
6
6
  Maintainer-email: laggykiller <chaudominic2@gmail.com>
@@ -365,21 +365,21 @@ Requires-Python: >=3.8
365
365
  Description-Content-Type: text/markdown
366
366
  License-File: LICENSE
367
367
  Requires-Dist: aiolimiter~=1.1.0
368
- Requires-Dist: anyio~=3.7.1
368
+ Requires-Dist: anyio~=4.3.0
369
369
  Requires-Dist: apngasm_python~=1.2.3
370
370
  Requires-Dist: av~=12.0.0
371
371
  Requires-Dist: beautifulsoup4~=4.12.3
372
- Requires-Dist: rookiepy~=0.3.6
372
+ Requires-Dist: rookiepy~=0.3.7
373
373
  Requires-Dist: imagequant~=1.1.1
374
374
  Requires-Dist: memory-tempfile~=2.2.3
375
375
  Requires-Dist: mergedeep~=1.3.4
376
376
  Requires-Dist: numpy>=1.22.4
377
- Requires-Dist: Pillow==10.1.0
377
+ Requires-Dist: Pillow~=10.3.0
378
378
  Requires-Dist: pyoxipng~=9.0.0
379
- Requires-Dist: python-telegram-bot~=20.5
379
+ Requires-Dist: python-telegram-bot~=21.1
380
380
  Requires-Dist: requests~=2.31.0
381
381
  Requires-Dist: rlottie_python~=1.3.4
382
- Requires-Dist: signalstickers-client~=3.3.0
382
+ Requires-Dist: signalstickers-client-fork-laggykiller~=3.3.0.post1
383
383
  Requires-Dist: sqlcipher3-wheels~=0.5.2.post1
384
384
  Requires-Dist: tqdm~=4.66.2
385
385
  Requires-Dist: ttkbootstrap-fork-laggykiller~=1.5.1
@@ -1,19 +1,19 @@
1
1
  aiolimiter~=1.1.0
2
- anyio~=3.7.1
2
+ anyio~=4.3.0
3
3
  apngasm_python~=1.2.3
4
4
  av~=12.0.0
5
5
  beautifulsoup4~=4.12.3
6
- rookiepy~=0.3.6
6
+ rookiepy~=0.3.7
7
7
  imagequant~=1.1.1
8
8
  memory-tempfile~=2.2.3
9
9
  mergedeep~=1.3.4
10
10
  numpy>=1.22.4
11
- Pillow==10.1.0
11
+ Pillow~=10.3.0
12
12
  pyoxipng~=9.0.0
13
- python-telegram-bot~=20.5
13
+ python-telegram-bot~=21.1
14
14
  requests~=2.31.0
15
15
  rlottie_python~=1.3.4
16
- signalstickers-client~=3.3.0
16
+ signalstickers-client-fork-laggykiller~=3.3.0.post1
17
17
  sqlcipher3-wheels~=0.5.2.post1
18
18
  tqdm~=4.66.2
19
19
  ttkbootstrap-fork-laggykiller~=1.5.1
@@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Tuple, Uni
9
9
  import numpy as np
10
10
  from PIL import Image
11
11
  from PIL import __version__ as PillowVersion
12
+ from PIL import features
12
13
 
13
14
  from sticker_convert.job_option import CompOption
14
15
  from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
@@ -32,6 +33,17 @@ MSG_FAIL_COMP = (
32
33
  "[F] Failed Compression {} -> {}, "
33
34
  "cannot get below limit {} with lowest quality under current settings (Best size: {})"
34
35
  )
36
+ MSG_PYWEBP_DUPFRAME = (
37
+ "[W] {} contains duplicated frame.\n"
38
+ " System WebP>=0.5.0 was not found, hence Pillow cannot be used\n"
39
+ " for creating animated webp. Using pywebp instead, which is known to\n"
40
+ " collapse same frames into single frame, causing problem with animation timing."
41
+ )
42
+ MSG_WEBP_PIL_DUPFRAME = (
43
+ "[W] {} contains duplicated frame.\n"
44
+ " Using Pillow to create animated webp to avoid same frames collapse\n"
45
+ " into single frame, but this is slower."
46
+ )
35
47
 
36
48
  YUV_RGB_MATRIX = np.array(
37
49
  [
@@ -41,6 +53,10 @@ YUV_RGB_MATRIX = np.array(
41
53
  ]
42
54
  )
43
55
 
56
+ # Whether animated WebP is supported
57
+ # See https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#saving-sequences
58
+ PIL_WEBP_ANIM = cast(bool, features.check("webp_anim")) # type: ignore
59
+
44
60
 
45
61
  def get_step_value(
46
62
  max_step: Optional[int],
@@ -179,6 +195,8 @@ class StickerConvert:
179
195
  self.result_step: Optional[int] = None
180
196
 
181
197
  self.apngasm = None
198
+ self.msg_pywebp_dupframe_displayed = False
199
+ self.msg_webp_pil_dupframe_displayed = False
182
200
 
183
201
  @staticmethod
184
202
  def convert(
@@ -394,7 +412,7 @@ class StickerConvert:
394
412
  with open(self.out_f, "wb+") as f:
395
413
  f.write(data)
396
414
 
397
- if result_step:
415
+ if result_step is not None:
398
416
  msg = MSG_DONE_COMP.format(
399
417
  self.in_f_name, self.out_f_name, self.result_size, result_step
400
418
  )
@@ -678,15 +696,52 @@ class StickerConvert:
678
696
  self._frames_export_apng()
679
697
  else:
680
698
  self._frames_export_png()
681
- elif self.out_f.suffix == ".webp" and is_animated:
699
+ elif self.out_f.suffix == ".webp":
682
700
  self._frames_export_webp()
683
701
  elif self.out_f.suffix == ".gif":
684
- self._frames_export_gif()
702
+ self._frames_export_pil_anim()
685
703
  elif self.out_f.suffix in (".webm", ".mp4", ".mkv") or is_animated:
686
704
  self._frames_export_pyav()
687
705
  else:
688
706
  self._frames_export_pil()
689
707
 
708
+ def _check_dup(self) -> bool:
709
+ if len(self.frames_processed) == 1:
710
+ return False
711
+
712
+ prev_frame = self.frames_processed[0]
713
+ for frame in self.frames_processed[1:]:
714
+ if np.array_equal(frame, prev_frame):
715
+ return True
716
+ prev_frame = frame
717
+
718
+ return False
719
+
720
+ def _frames_export_webp(self) -> None:
721
+ has_dup_frames = self._check_dup()
722
+ if self.fps:
723
+ # It was noted that pywebp would collapse all frames.
724
+ # aed005b attempted to fix this by creating webp with
725
+ # variable frame duration. However, the webp created would
726
+ # not be accepted by WhatsApp.
727
+ # Therefore, we are preferring Pillow over pywebp.
728
+ if has_dup_frames:
729
+ if PIL_WEBP_ANIM:
730
+ # Warn that using Pillow is slower
731
+ if not self.msg_webp_pil_dupframe_displayed:
732
+ self.cb.put(MSG_WEBP_PIL_DUPFRAME.format(self.in_f_name))
733
+ self.msg_webp_pil_dupframe_displayed = True
734
+ self._frames_export_pil_anim()
735
+ else:
736
+ if not self.msg_pywebp_dupframe_displayed:
737
+ self.cb.put(MSG_PYWEBP_DUPFRAME.format(self.in_f_name))
738
+ self.msg_pywebp_dupframe_displayed = True
739
+ self._frames_export_pywebp()
740
+ else:
741
+ self._frames_export_pywebp()
742
+ else:
743
+ self._frames_export_pil()
744
+
690
745
  def _frames_export_pil(self) -> None:
691
746
  with Image.fromarray(self.frames_processed[0]) as im: # type: ignore
692
747
  im.save(
@@ -710,7 +765,7 @@ class StickerConvert:
710
765
  codec = "apng"
711
766
  pixel_format = "rgba"
712
767
  options["plays"] = "0"
713
- elif self.out_f.suffix in (".webp", ".webm", ".mkv"):
768
+ elif self.out_f.suffix in (".webm", ".mkv"):
714
769
  codec = "libvpx-vp9"
715
770
  pixel_format = "yuva420p"
716
771
  options["loop"] = "0"
@@ -734,7 +789,7 @@ class StickerConvert:
734
789
  output.mux(out_stream.encode(av_frame))
735
790
  output.mux(out_stream.encode())
736
791
 
737
- def _frames_export_gif(self) -> None:
792
+ def _frames_export_pil_anim(self) -> None:
738
793
  extra_kwargs: Dict[str, Any] = {}
739
794
 
740
795
  # disposal=2 on gif cause flicker in image with transparency
@@ -745,25 +800,34 @@ class StickerConvert:
745
800
  else:
746
801
  extra_kwargs["optimize"] = True
747
802
 
748
- # GIF can only have one alpha color
749
- # Change lowest alpha to alpha=0
750
- # Only keep alpha=0 and alpha=255, nothing in between
751
- frames_processed = np.array(self.frames_processed)
752
- alpha = frames_processed[:, :, :, 3]
753
- alpha_min = np.min(alpha) # type: ignore
754
- if alpha_min < 255:
755
- alpha[alpha > alpha_min] = 255
756
- alpha[alpha == alpha_min] = 0
757
-
758
- if 0 in alpha:
759
- extra_kwargs["transparency"] = 0
760
- extra_kwargs["disposal"] = 2
761
- im_out = [self.quantize(Image.fromarray(i)) for i in frames_processed] # type: ignore
803
+ if self.out_f.suffix == ".gif":
804
+ # GIF can only have one alpha color
805
+ # Change lowest alpha to alpha=0
806
+ # Only keep alpha=0 and alpha=255, nothing in between
807
+ frames_processed = np.array(self.frames_processed)
808
+ alpha = frames_processed[:, :, :, 3]
809
+ alpha_min = np.min(alpha) # type: ignore
810
+ if alpha_min < 255:
811
+ alpha[alpha > alpha_min] = 255
812
+ alpha[alpha == alpha_min] = 0
813
+
814
+ if 0 in alpha:
815
+ extra_kwargs["transparency"] = 0
816
+ extra_kwargs["disposal"] = 2
817
+ im_out = [self.quantize(Image.fromarray(i)) for i in frames_processed] # type: ignore
818
+ else:
819
+ im_out = [
820
+ self.quantize(Image.fromarray(i).convert("RGB")).convert("RGB") # type: ignore
821
+ for i in frames_processed
822
+ ]
823
+ extra_kwargs["format"] = "GIF"
824
+ elif self.out_f.suffix == ".webp":
825
+ im_out = [Image.fromarray(i) for i in self.frames_processed] # type: ignore
826
+ extra_kwargs["format"] = "WebP"
827
+ extra_kwargs["minimize_size"] = True
828
+ extra_kwargs["method"] = 6
762
829
  else:
763
- im_out = [
764
- self.quantize(Image.fromarray(i).convert("RGB")).convert("RGB") # type: ignore
765
- for i in frames_processed
766
- ]
830
+ raise RuntimeError(f"Invalid format {self.out_f.suffix}")
767
831
 
768
832
  if self.fps:
769
833
  extra_kwargs["save_all"] = True
@@ -773,12 +837,11 @@ class StickerConvert:
773
837
 
774
838
  im_out[0].save(
775
839
  self.tmp_f,
776
- format="GIF",
777
840
  quality=self.quality,
778
841
  **extra_kwargs,
779
842
  )
780
843
 
781
- def _frames_export_webp(self) -> None:
844
+ def _frames_export_pywebp(self) -> None:
782
845
  import webp # type: ignore
783
846
 
784
847
  assert self.fps
@@ -786,25 +849,10 @@ class StickerConvert:
786
849
  config = webp.WebPConfig.new(quality=self.quality) # type: ignore
787
850
  enc = webp.WebPAnimEncoder.new(self.res_w, self.res_h) # type: ignore
788
851
  timestamp_ms = 0
789
- timestamp_inc = int(1000 / self.fps)
790
-
791
- pic = webp.WebPPicture.from_numpy(self.frames_processed[0]) # type: ignore
792
- enc.encode_frame(pic, 0, config=config) # type: ignore
793
-
794
- frame_num = 1
795
- frame_num_prev = 1
796
- frame_total = len(self.frames_processed)
797
- while frame_num < frame_total - 1:
798
- while frame_num < frame_total - 1 and np.array_equal(
799
- self.frames_processed[frame_num_prev],
800
- self.frames_processed[frame_num],
801
- ):
802
- timestamp_ms += timestamp_inc
803
- frame_num += 1
804
- pic = webp.WebPPicture.from_numpy(self.frames_processed[frame_num]) # type: ignore
852
+ for frame in self.frames_processed:
853
+ pic = webp.WebPPicture.from_numpy(frame) # type: ignore
805
854
  enc.encode_frame(pic, timestamp_ms, config=config) # type: ignore
806
- frame_num_prev = frame_num
807
-
855
+ timestamp_ms += int(1000 / self.fps)
808
856
  anim_data = enc.assemble(timestamp_ms) # type: ignore
809
857
  self.tmp_f.write(anim_data.buffer()) # type: ignore
810
858
 
@@ -3,9 +3,9 @@ from pathlib import Path
3
3
  from typing import Dict, Optional
4
4
 
5
5
  import anyio
6
- from signalstickers_client import StickersClient # type: ignore
7
- from signalstickers_client.errors import SignalException # type: ignore
8
- from signalstickers_client.models import StickerPack # type: ignore
6
+ from signalstickers_client.errors import SignalException
7
+ from signalstickers_client.models import StickerPack
8
+ from signalstickers_client.stickersclient import StickersClient
9
9
 
10
10
  from sticker_convert.downloaders.download_base import DownloadBase
11
11
  from sticker_convert.job_option import CredOption
@@ -21,7 +21,7 @@ class DownloadSignal(DownloadBase):
21
21
  @staticmethod
22
22
  async def get_pack(pack_id: str, pack_key: str) -> StickerPack:
23
23
  async with StickersClient() as client:
24
- pack = await client.get_pack(pack_id, pack_key) # type: ignore
24
+ pack = await client.get_pack(pack_id, pack_key)
25
25
 
26
26
  return pack
27
27
 
@@ -32,14 +32,14 @@ class DownloadSignal(DownloadBase):
32
32
  None,
33
33
  {
34
34
  "set_progress_mode": "determinate",
35
- "steps": len(pack.stickers), # type: ignore
35
+ "steps": len(pack.stickers),
36
36
  },
37
37
  )
38
38
  )
39
39
 
40
40
  emoji_dict: Dict[str, str] = {}
41
- for sticker in pack.stickers: # type: ignore
42
- f_id = str(sticker.id).zfill(3) # type: ignore
41
+ for sticker in pack.stickers:
42
+ f_id = str(sticker.id).zfill(3)
43
43
  f_path = Path(self.out_dir, f_id)
44
44
  with open(f_path, "wb") as f:
45
45
  f.write(sticker.image_data) # type: ignore
@@ -79,7 +79,7 @@ class CompressWastickers(UploadBase):
79
79
  else:
80
80
  ext = ".png"
81
81
 
82
- dst = Path(tempdir, str(num) + ext)
82
+ dst = Path(tempdir, f"sticker_{num+1}{ext}")
83
83
 
84
84
  if FormatVerify.check_file(
85
85
  src, spec=self.webp_spec
@@ -114,7 +114,7 @@ class CompressWastickers(UploadBase):
114
114
  opt_comp_merged.merge(self.spec_cover)
115
115
 
116
116
  cover_path_old = MetadataHandler.get_cover(self.opt_output.dir)
117
- cover_path_new = Path(pack_dir, "100.png")
117
+ cover_path_new = Path(pack_dir, "tray.png")
118
118
  if cover_path_old:
119
119
  if FormatVerify.check_file(cover_path_old, spec=self.spec_cover):
120
120
  shutil.copy(cover_path_old, cover_path_new)
@@ -142,7 +142,7 @@ class CompressWastickers(UploadBase):
142
142
  self.cb_return,
143
143
  )
144
144
 
145
- MetadataHandler.set_metadata(pack_dir, author=author, title=title)
145
+ MetadataHandler.set_metadata(pack_dir, author=author, title=title, newline=True)
146
146
 
147
147
  @staticmethod
148
148
  def start(
@@ -4,9 +4,9 @@ from pathlib import Path
4
4
  from typing import Any, Dict, List
5
5
 
6
6
  import anyio
7
- from signalstickers_client import StickersClient # type: ignore
8
- from signalstickers_client.errors import SignalException # type: ignore
9
- from signalstickers_client.models import LocalStickerPack, Sticker # type: ignore
7
+ from signalstickers_client.errors import SignalException
8
+ from signalstickers_client.models import LocalStickerPack, Sticker
9
+ from signalstickers_client.stickersclient import StickersClient
10
10
 
11
11
  from sticker_convert.converter import StickerConvert
12
12
  from sticker_convert.job_option import CompOption, CredOption, OutputOption
@@ -39,7 +39,7 @@ class UploadSignal(UploadBase):
39
39
  @staticmethod
40
40
  async def upload_pack(pack: LocalStickerPack, uuid: str, password: str) -> str:
41
41
  async with StickersClient(uuid, password) as client:
42
- pack_id, pack_key = await client.upload_pack(pack) # type: ignore
42
+ pack_id, pack_key = await client.upload_pack(pack)
43
43
 
44
44
  result = (
45
45
  f"https://signal.art/addstickers/#pack_id={pack_id}&pack_key={pack_key}"
@@ -53,7 +53,7 @@ class UploadSignal(UploadBase):
53
53
  self.cb.put(f"Verifying {src} for uploading to signal")
54
54
 
55
55
  sticker = Sticker()
56
- sticker.id = pack.nb_stickers # type: ignore
56
+ sticker.id = pack.nb_stickers
57
57
 
58
58
  emoji = emoji_dict.get(Path(src).stem, None)
59
59
  if not emoji:
@@ -61,7 +61,7 @@ class UploadSignal(UploadBase):
61
61
  f"Warning: Cannot find emoji for file {Path(src).name}, skip uploading this file..."
62
62
  )
63
63
  continue
64
- sticker.emoji = emoji[:1] # type: ignore
64
+ sticker.emoji = emoji[:1]
65
65
 
66
66
  if Path(src).suffix == ".webp":
67
67
  spec_choice = self.webp_spec
@@ -84,10 +84,10 @@ class UploadSignal(UploadBase):
84
84
 
85
85
  assert isinstance(image_data, bytes)
86
86
 
87
- sticker.image_data = image_data # type: ignore
87
+ sticker.image_data = image_data
88
88
  else:
89
89
  with open(src, "rb") as f:
90
- sticker.image_data = f.read() # type: ignore
90
+ sticker.image_data = f.read()
91
91
 
92
92
  pack._addsticker(sticker) # type: ignore
93
93
 
@@ -140,8 +140,8 @@ class UploadSignal(UploadBase):
140
140
  )
141
141
  for pack_title, stickers in packs.items():
142
142
  pack = LocalStickerPack()
143
- pack.title = pack_title # type: ignore
144
- pack.author = author # type: ignore
143
+ pack.title = pack_title
144
+ pack.author = author
145
145
 
146
146
  self.add_stickers_to_pack(pack, stickers, emoji_dict)
147
147
  self.cb.put(f"Uploading pack {pack_title}")
@@ -2,7 +2,7 @@
2
2
  import copy
3
3
  import re
4
4
  from pathlib import Path
5
- from typing import Any, Dict, List, Optional, Tuple, Union, cast
5
+ from typing import Any, Dict, List, Optional, Union, cast
6
6
 
7
7
  import anyio
8
8
  from telegram import InputSticker, Sticker
@@ -96,7 +96,7 @@ class UploadTelegram(UploadBase):
96
96
  "[^0-9a-zA-Z]+", "_", pack_short_name
97
97
  ) # name used in url, only alphanum and underscore only
98
98
 
99
- sticker_set = None
99
+ sticker_set: Any = None
100
100
  try:
101
101
  sticker_set = await bot.get_sticker_set(
102
102
  pack_short_name,
@@ -152,11 +152,10 @@ class UploadTelegram(UploadBase):
152
152
  else:
153
153
  sticker_type = Sticker.REGULAR
154
154
 
155
- input_stickers: List[Tuple[Path, InputSticker]] = []
155
+ init_input_stickers: List[InputSticker] = []
156
156
  sticker_format = None
157
- cover_spec_choice = None
158
- ext = None
159
- for src in stickers:
157
+ sticker_format_prev = None
158
+ for count, src in enumerate(stickers):
160
159
  self.cb.put(f"Verifying {src} for uploading to telegram")
161
160
 
162
161
  emoji = emoji_dict.get(Path(src).stem, None)
@@ -175,16 +174,13 @@ class UploadTelegram(UploadBase):
175
174
  ext = Path(src).suffix
176
175
  if ext == ".tgs":
177
176
  spec_choice = self.tgs_spec
178
- cover_spec_choice = self.tgs_cover_spec
179
177
  sticker_format = "animated"
180
178
  elif ext == ".webm":
181
179
  spec_choice = self.webm_spec
182
- cover_spec_choice = self.webm_cover_spec
183
180
  sticker_format = "video"
184
181
  else:
185
182
  ext = ".png"
186
183
  spec_choice = self.png_spec
187
- cover_spec_choice = self.png_cover_spec
188
184
  sticker_format = "static"
189
185
 
190
186
  if self.opt_output.option == "telegram_emoji":
@@ -203,81 +199,98 @@ class UploadTelegram(UploadBase):
203
199
  )
204
200
  sticker_bytes = cast(bytes, convert_result)
205
201
 
206
- input_stickers.append(
207
- (src, InputSticker(sticker=sticker_bytes, emoji_list=emoji_list))
202
+ input_sticker = InputSticker(
203
+ sticker=sticker_bytes,
204
+ emoji_list=emoji_list,
205
+ format=sticker_format,
208
206
  )
209
207
 
208
+ if sticker_set is None:
209
+ if count < 50 and (
210
+ sticker_format_prev is None
211
+ or sticker_format_prev == sticker_format
212
+ ):
213
+ init_input_stickers.append(input_sticker)
214
+ else:
215
+ start_msg = f"Creating pack and bulk uploading {count} stickers with same format of {pack_short_name}"
216
+ finish_msg = f"Created pack and bulk uploaded {count} stickers with same format of {pack_short_name}"
217
+ error_msg = f"Cannot create pack and bulk upload {count} stickers with same format of {pack_short_name} due to"
218
+ self.cb.put(start_msg)
219
+ try:
220
+ await bot.create_new_sticker_set(
221
+ user_id=self.telegram_userid,
222
+ name=pack_short_name,
223
+ title=pack_title,
224
+ stickers=init_input_stickers,
225
+ sticker_type=sticker_type,
226
+ )
227
+ sticker_set = True
228
+ self.cb.put(finish_msg)
229
+ except TelegramError as e:
230
+ self.cb.put(f"{error_msg} {e}")
231
+ return None
232
+ else:
233
+ try:
234
+ # We could use tg.start_soon() here
235
+ # But this would disrupt the order of stickers
236
+ await bot.add_sticker_to_set(
237
+ user_id=self.telegram_userid,
238
+ name=pack_short_name,
239
+ sticker=input_sticker,
240
+ )
241
+ self.cb.put(f"Uploaded sticker {src} of {pack_short_name}")
242
+ except BadRequest as e:
243
+ self.cb.put(
244
+ f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
245
+ )
246
+ if str(e) == "Stickerpack_not_found":
247
+ self.cb.put(
248
+ "Hint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
249
+ )
250
+ except TelegramError as e:
251
+ self.cb.put(
252
+ f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
253
+ )
254
+
255
+ sticker_format_prev = sticker_format
256
+
210
257
  cover_path = MetadataHandler.get_cover(self.opt_output.dir)
211
- thumbnail_bytes: Union[None, bytes, Path] = None
212
- if cover_path and cover_spec_choice and ext:
258
+ if cover_path:
259
+ thumbnail_bytes: Union[None, bytes, Path] = None
260
+ cover_ext = Path(cover_path).suffix
261
+
262
+ if cover_ext == ".tgs":
263
+ thumbnail_format = "animated"
264
+ cover_spec_choice = self.tgs_cover_spec
265
+ elif cover_ext == ".webm":
266
+ thumbnail_format = "video"
267
+ cover_spec_choice = self.webm_cover_spec
268
+ else:
269
+ cover_ext = ".png"
270
+ thumbnail_format = "static"
271
+ cover_spec_choice = self.png_cover_spec
272
+
213
273
  if FormatVerify.check_file(cover_path, spec=cover_spec_choice):
214
274
  with open(cover_path, "rb") as f:
215
275
  thumbnail_bytes = f.read()
216
276
  else:
217
277
  _, _, thumbnail_bytes, _ = StickerConvert.convert(
218
278
  cover_path,
219
- Path(f"bytes{ext}"),
279
+ Path(f"bytes{cover_ext}"),
220
280
  self.opt_comp_cover_merged,
221
281
  self.cb,
222
282
  self.cb_return,
223
283
  )
224
284
 
225
- if sticker_set is None and sticker_format is not None:
226
- if len(input_stickers) > 50:
227
- amount_str = "first 50"
228
- else:
229
- amount_str = "all"
230
- start_msg = f"Creating pack and bulk uploading {amount_str} stickers of {pack_short_name}"
231
- finish_msg = f"Created pack and bulk uploaded {amount_str} stickers of {pack_short_name}"
232
- error_msg = f"Cannot create pack and bulk upload {amount_str} stickers of {pack_short_name} due to"
233
- self.cb.put(start_msg)
234
- try:
235
- await bot.create_new_sticker_set(
236
- user_id=self.opt_cred.telegram_userid,
237
- name=pack_short_name,
238
- title=pack_title,
239
- stickers=[a for _, a in input_stickers[:50]],
240
- sticker_format=sticker_format,
241
- sticker_type=sticker_type,
242
- )
243
- self.cb.put(finish_msg)
244
- input_stickers = input_stickers[50:]
245
- except TelegramError as e:
246
- self.cb.put(f"{error_msg} {e}")
247
- return None
248
-
249
- for src, sticker in input_stickers:
250
- try:
251
- # We could use tg.start_soon() here
252
- # But this would disrupt the order of stickers
253
- await bot.add_sticker_to_set(
254
- user_id=self.opt_cred.telegram_userid,
255
- name=pack_short_name,
256
- sticker=sticker,
257
- )
258
- self.cb.put(f"Uploaded sticker {src} of {pack_short_name}")
259
- except BadRequest as e:
260
- self.cb.put(
261
- f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
262
- )
263
- if str(e) == "Stickerpack_not_found":
264
- self.cb.put(
265
- "Hint: You might had deleted and recreated pack too quickly. Wait about 3 minutes and try again."
266
- )
267
- except TelegramError as e:
268
- self.cb.put(
269
- f"Cannot upload sticker {src} of {pack_short_name} due to {e}"
270
- )
271
-
272
- if thumbnail_bytes is not None:
273
285
  try:
274
286
  self.cb.put(
275
287
  f"Uploading cover (thumbnail) of pack {pack_short_name}"
276
288
  )
277
289
  await bot.set_sticker_set_thumbnail(
278
290
  name=pack_short_name,
279
- user_id=self.opt_cred.telegram_userid,
291
+ user_id=self.telegram_userid,
280
292
  thumbnail=thumbnail_bytes,
293
+ format=thumbnail_format,
281
294
  )
282
295
  self.cb.put(f"Uploaded cover (thumbnail) of pack {pack_short_name}")
283
296
  except TelegramError as e:
@@ -300,6 +313,12 @@ class UploadTelegram(UploadBase):
300
313
  self.cb.put("Token and userid required for uploading to telegram")
301
314
  return urls
302
315
 
316
+ if self.opt_cred.telegram_userid.isnumeric():
317
+ self.telegram_userid = int(self.opt_cred.telegram_userid)
318
+ else:
319
+ self.cb.put("Invalid userid, should contain numbers only")
320
+ return urls
321
+
303
322
  title, _, emoji_dict = MetadataHandler.get_metadata(
304
323
  self.opt_output.dir,
305
324
  title=self.opt_output.title,
@@ -327,11 +346,18 @@ class UploadTelegram(UploadBase):
327
346
  )
328
347
 
329
348
  assert title is not None
349
+ assert emoji_dict is not None
350
+
351
+ if self.opt_output.option == "telegram_emoji":
352
+ file_per_pack = 200
353
+ else:
354
+ file_per_pack = 120
355
+
330
356
  packs = MetadataHandler.split_sticker_packs(
331
357
  self.opt_output.dir,
332
358
  title=title,
333
- file_per_anim_pack=50,
334
- file_per_image_pack=120,
359
+ file_per_anim_pack=file_per_pack,
360
+ file_per_image_pack=file_per_pack,
335
361
  separate_image_anim=not self.opt_comp.fake_vid,
336
362
  )
337
363
 
@@ -5,41 +5,35 @@ from http.cookiejar import CookieJar
5
5
  from typing import Any, Callable, Dict, List, Optional, Union
6
6
 
7
7
  import requests
8
- import rookiepy # type: ignore
8
+ import rookiepy
9
9
 
10
10
 
11
11
  class GetLineAuth:
12
12
  def get_cred(self) -> Optional[str]:
13
13
  browsers: List[Callable[..., Any]] = [
14
- rookiepy.load, # type: ignore # Supposed to load from any browser, but may fail
15
- rookiepy.firefox, # type: ignore
16
- rookiepy.libre_wolf, # type: ignore
17
- rookiepy.chrome, # type: ignore
18
- rookiepy.chromium, # type: ignore
19
- rookiepy.brave, # type: ignore
20
- rookiepy.edge, # type: ignore
21
- rookiepy.opera, # type: ignore
22
- rookiepy.vivaldi, # type: ignore
14
+ rookiepy.load, # Supposed to load from any browser, but may fail
15
+ rookiepy.firefox,
16
+ rookiepy.librewolf,
17
+ rookiepy.chrome,
18
+ rookiepy.chromium,
19
+ rookiepy.brave,
20
+ rookiepy.edge,
21
+ rookiepy.opera,
22
+ rookiepy.vivaldi,
23
23
  ]
24
24
 
25
- # https://github.com/thewh1teagle/rookie/pull/24
26
- if "libre_wolf" in rookiepy.__all__:
27
- browsers.extend(rookiepy.libre_wolf) # type: ignore
28
- else:
29
- browsers.extend(rookiepy.librewolf) # type: ignore
30
-
31
25
  if platform.system() == "Windows":
32
26
  browsers.extend(
33
27
  [
34
- rookiepy.opera_gx, # type: ignore
35
- rookiepy.internet_explorer, # type: ignore
28
+ rookiepy.opera_gx,
29
+ rookiepy.internet_explorer,
36
30
  ]
37
31
  )
38
32
  elif platform.system() == "Darwin":
39
33
  browsers.extend(
40
34
  [
41
- rookiepy.opera_gx, # type: ignore
42
- rookiepy.safari, # type: ignore
35
+ rookiepy.opera_gx,
36
+ rookiepy.safari,
43
37
  ]
44
38
  )
45
39
 
@@ -48,7 +42,7 @@ class GetLineAuth:
48
42
  for browser in browsers:
49
43
  try:
50
44
  cookies_dict = browser(["store.line.me"])
51
- cookies_jar = rookiepy.to_cookiejar(cookies_dict) # type: ignore
45
+ cookies_jar = rookiepy.to_cookiejar(cookies_dict)
52
46
 
53
47
  if GetLineAuth.validate_cookies(cookies_jar):
54
48
  break
@@ -133,16 +133,21 @@ class MetadataHandler:
133
133
  title: Optional[str] = None,
134
134
  author: Optional[str] = None,
135
135
  emoji_dict: Optional[Dict[str, str]] = None,
136
+ newline: bool = False,
136
137
  ) -> None:
137
138
  title_path = Path(directory, "title.txt")
138
139
  if title is not None:
139
140
  with open(title_path, "w+", encoding="utf-8") as f:
140
141
  f.write(title)
142
+ if newline:
143
+ f.write("\n")
141
144
 
142
145
  author_path = Path(directory, "author.txt")
143
146
  if author is not None:
144
147
  with open(author_path, "w+", encoding="utf-8") as f:
145
148
  f.write(author)
149
+ if newline:
150
+ f.write("\n")
146
151
 
147
152
  emoji_path = Path(directory, "emoji.txt")
148
153
  if emoji_dict is not None:
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
- __version__ = "2.8.2"
3
+ __version__ = "2.8.4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.8.2
3
+ Version: 2.8.4
4
4
  Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, iMessage. Written in Python.
5
5
  Author-email: laggykiller <chaudominic2@gmail.com>
6
6
  Maintainer-email: laggykiller <chaudominic2@gmail.com>
@@ -365,21 +365,21 @@ Requires-Python: >=3.8
365
365
  Description-Content-Type: text/markdown
366
366
  License-File: LICENSE
367
367
  Requires-Dist: aiolimiter~=1.1.0
368
- Requires-Dist: anyio~=3.7.1
368
+ Requires-Dist: anyio~=4.3.0
369
369
  Requires-Dist: apngasm_python~=1.2.3
370
370
  Requires-Dist: av~=12.0.0
371
371
  Requires-Dist: beautifulsoup4~=4.12.3
372
- Requires-Dist: rookiepy~=0.3.6
372
+ Requires-Dist: rookiepy~=0.3.7
373
373
  Requires-Dist: imagequant~=1.1.1
374
374
  Requires-Dist: memory-tempfile~=2.2.3
375
375
  Requires-Dist: mergedeep~=1.3.4
376
376
  Requires-Dist: numpy>=1.22.4
377
- Requires-Dist: Pillow==10.1.0
377
+ Requires-Dist: Pillow~=10.3.0
378
378
  Requires-Dist: pyoxipng~=9.0.0
379
- Requires-Dist: python-telegram-bot~=20.5
379
+ Requires-Dist: python-telegram-bot~=21.1
380
380
  Requires-Dist: requests~=2.31.0
381
381
  Requires-Dist: rlottie_python~=1.3.4
382
- Requires-Dist: signalstickers-client~=3.3.0
382
+ Requires-Dist: signalstickers-client-fork-laggykiller~=3.3.0.post1
383
383
  Requires-Dist: sqlcipher3-wheels~=0.5.2.post1
384
384
  Requires-Dist: tqdm~=4.66.2
385
385
  Requires-Dist: ttkbootstrap-fork-laggykiller~=1.5.1
@@ -1,19 +1,19 @@
1
1
  aiolimiter~=1.1.0
2
- anyio~=3.7.1
2
+ anyio~=4.3.0
3
3
  apngasm_python~=1.2.3
4
4
  av~=12.0.0
5
5
  beautifulsoup4~=4.12.3
6
- rookiepy~=0.3.6
6
+ rookiepy~=0.3.7
7
7
  imagequant~=1.1.1
8
8
  memory-tempfile~=2.2.3
9
9
  mergedeep~=1.3.4
10
10
  numpy>=1.22.4
11
- Pillow==10.1.0
11
+ Pillow~=10.3.0
12
12
  pyoxipng~=9.0.0
13
- python-telegram-bot~=20.5
13
+ python-telegram-bot~=21.1
14
14
  requests~=2.31.0
15
15
  rlottie_python~=1.3.4
16
- signalstickers-client~=3.3.0
16
+ signalstickers-client-fork-laggykiller~=3.3.0.post1
17
17
  sqlcipher3-wheels~=0.5.2.post1
18
18
  tqdm~=4.66.2
19
19
  ttkbootstrap-fork-laggykiller~=1.5.1
File without changes