sticker-convert 2.13.3.0__py3-none-any.whl → 2.17.0.0__py3-none-any.whl

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 (93) hide show
  1. sticker_convert/__main__.py +24 -27
  2. sticker_convert/auth/__init__.py +0 -0
  3. sticker_convert/auth/auth_base.py +19 -0
  4. sticker_convert/{utils/auth/get_discord_auth.py → auth/auth_discord.py} +149 -118
  5. sticker_convert/{utils/auth/get_kakao_auth.py → auth/auth_kakao_android_login.py} +331 -330
  6. sticker_convert/auth/auth_kakao_desktop_login.py +327 -0
  7. sticker_convert/{utils/auth/get_kakao_desktop_auth.py → auth/auth_kakao_desktop_memdump.py} +281 -263
  8. sticker_convert/{utils/auth/get_line_auth.py → auth/auth_line.py} +98 -80
  9. sticker_convert/{utils/auth/get_signal_auth.py → auth/auth_signal.py} +139 -135
  10. sticker_convert/auth/auth_telethon.py +161 -0
  11. sticker_convert/{utils/auth/get_viber_auth.py → auth/auth_viber.py} +250 -235
  12. sticker_convert/{utils/auth → auth}/telegram_api.py +736 -675
  13. sticker_convert/cli.py +623 -608
  14. sticker_convert/converter.py +1093 -1084
  15. sticker_convert/definitions.py +4 -0
  16. sticker_convert/downloaders/download_band.py +111 -110
  17. sticker_convert/downloaders/download_base.py +171 -166
  18. sticker_convert/downloaders/download_discord.py +92 -91
  19. sticker_convert/downloaders/download_kakao.py +417 -404
  20. sticker_convert/downloaders/download_line.py +484 -475
  21. sticker_convert/downloaders/download_ogq.py +80 -79
  22. sticker_convert/downloaders/download_signal.py +108 -105
  23. sticker_convert/downloaders/download_telegram.py +56 -55
  24. sticker_convert/downloaders/download_viber.py +121 -120
  25. sticker_convert/gui.py +788 -873
  26. sticker_convert/gui_components/frames/comp_frame.py +180 -166
  27. sticker_convert/gui_components/frames/config_frame.py +156 -113
  28. sticker_convert/gui_components/frames/control_frame.py +32 -30
  29. sticker_convert/gui_components/frames/cred_frame.py +232 -233
  30. sticker_convert/gui_components/frames/input_frame.py +139 -137
  31. sticker_convert/gui_components/frames/output_frame.py +112 -110
  32. sticker_convert/gui_components/frames/right_clicker.py +25 -23
  33. sticker_convert/gui_components/windows/advanced_compression_window.py +757 -757
  34. sticker_convert/gui_components/windows/base_window.py +7 -2
  35. sticker_convert/gui_components/windows/discord_get_auth_window.py +79 -82
  36. sticker_convert/gui_components/windows/kakao_get_auth_window.py +511 -321
  37. sticker_convert/gui_components/windows/line_get_auth_window.py +94 -102
  38. sticker_convert/gui_components/windows/signal_get_auth_window.py +84 -89
  39. sticker_convert/gui_components/windows/viber_get_auth_window.py +168 -168
  40. sticker_convert/ios-message-stickers-template/.github/FUNDING.yml +3 -3
  41. sticker_convert/ios-message-stickers-template/README.md +10 -10
  42. sticker_convert/ios-message-stickers-template/stickers/Info.plist +43 -43
  43. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Info.plist +31 -31
  44. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Contents.json +6 -6
  45. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json +20 -20
  46. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Contents.json +9 -9
  47. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Contents.json +9 -9
  48. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Contents.json +9 -9
  49. sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json +91 -91
  50. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.pbxproj +364 -364
  51. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -7
  52. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -8
  53. sticker_convert/ios-message-stickers-template/stickers.xcodeproj/xcuserdata/niklaspeterson.xcuserdatad/xcschemes/xcschememanagement.plist +14 -14
  54. sticker_convert/job.py +166 -130
  55. sticker_convert/job_option.py +1 -0
  56. sticker_convert/locales/en_US/LC_MESSAGES/base.mo +0 -0
  57. sticker_convert/locales/ja_JP/LC_MESSAGES/base.mo +0 -0
  58. sticker_convert/locales/zh_CN/LC_MESSAGES/base.mo +0 -0
  59. sticker_convert/locales/zh_TW/LC_MESSAGES/base.mo +0 -0
  60. sticker_convert/py.typed +0 -0
  61. sticker_convert/resources/NotoColorEmoji.ttf +0 -0
  62. sticker_convert/resources/help.ja_JP.json +88 -0
  63. sticker_convert/resources/help.json +10 -7
  64. sticker_convert/resources/help.zh_CN.json +88 -0
  65. sticker_convert/resources/help.zh_TW.json +88 -0
  66. sticker_convert/resources/input.ja_JP.json +74 -0
  67. sticker_convert/resources/input.json +121 -121
  68. sticker_convert/resources/input.zh_CN.json +74 -0
  69. sticker_convert/resources/input.zh_TW.json +74 -0
  70. sticker_convert/resources/output.ja_JP.json +38 -0
  71. sticker_convert/resources/output.zh_CN.json +38 -0
  72. sticker_convert/resources/output.zh_TW.json +38 -0
  73. sticker_convert/uploaders/compress_wastickers.py +186 -177
  74. sticker_convert/uploaders/upload_base.py +44 -35
  75. sticker_convert/uploaders/upload_signal.py +218 -203
  76. sticker_convert/uploaders/upload_telegram.py +353 -338
  77. sticker_convert/uploaders/upload_viber.py +178 -169
  78. sticker_convert/uploaders/xcode_imessage.py +295 -286
  79. sticker_convert/utils/callback.py +238 -6
  80. sticker_convert/utils/emoji.py +16 -4
  81. sticker_convert/utils/files/json_resources_loader.py +24 -19
  82. sticker_convert/utils/files/metadata_handler.py +3 -3
  83. sticker_convert/utils/translate.py +108 -0
  84. sticker_convert/utils/url_detect.py +40 -37
  85. sticker_convert/version.py +1 -1
  86. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/METADATA +89 -74
  87. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/RECORD +91 -74
  88. sticker_convert/utils/auth/telethon_setup.py +0 -97
  89. sticker_convert/utils/singletons.py +0 -18
  90. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/WHEEL +0 -0
  91. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/entry_points.txt +0 -0
  92. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/licenses/LICENSE +0 -0
  93. {sticker_convert-2.13.3.0.dist-info → sticker_convert-2.17.0.0.dist-info}/top_level.txt +0 -0
@@ -1,203 +1,218 @@
1
- #!/usr/bin/env python3
2
- import copy
3
- from pathlib import Path
4
- from typing import Any, Dict, List, Optional, Tuple
5
-
6
- import anyio
7
- from signalstickers_client.errors import SignalException
8
- from signalstickers_client.models import LocalStickerPack, Sticker
9
- from signalstickers_client.stickersclient import StickersClient
10
-
11
- from sticker_convert.converter import StickerConvert
12
- from sticker_convert.job_option import CompOption, CredOption, OutputOption
13
- from sticker_convert.uploaders.upload_base import UploadBase
14
- from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
15
- from sticker_convert.utils.emoji import extract_emojis
16
- from sticker_convert.utils.files.metadata_handler import MetadataHandler
17
- from sticker_convert.utils.media.codec_info import CodecInfo
18
- from sticker_convert.utils.media.format_verify import FormatVerify
19
-
20
-
21
- class UploadSignal(UploadBase):
22
- def __init__(self, *args: Any, **kwargs: Any) -> None:
23
- super().__init__(*args, **kwargs)
24
-
25
- self.base_spec.set_size_max(300000)
26
- self.base_spec.set_res_max(512)
27
- self.base_spec.duration_max = 3000
28
-
29
- self.png_spec = copy.deepcopy(self.base_spec)
30
- self.png_spec.set_format((".apng",))
31
-
32
- self.webp_spec = copy.deepcopy(self.base_spec)
33
- self.webp_spec.format_img = (".webp",)
34
- self.webp_spec.animated = False
35
-
36
- self.opt_comp_merged = copy.deepcopy(self.opt_comp)
37
- self.opt_comp_merged.merge(self.base_spec)
38
-
39
- @staticmethod
40
- async def upload_pack(pack: LocalStickerPack, uuid: str, password: str) -> str:
41
- async with StickersClient(uuid, password) as client:
42
- pack_id, pack_key = await client.upload_pack(pack)
43
-
44
- result = (
45
- f"https://signal.art/addstickers/#pack_id={pack_id}&pack_key={pack_key}"
46
- )
47
- return result
48
-
49
- def create_sticker(
50
- self, src: Path, emoji_dict: Dict[str, str]
51
- ) -> Optional[Sticker]:
52
- self.cb.put(f"Verifying {src} for uploading to signal")
53
-
54
- sticker = Sticker()
55
-
56
- emoji = extract_emojis(emoji_dict.get(Path(src).stem, ""))
57
- if emoji == "":
58
- self.cb.put(
59
- f"Warning: Cannot find emoji for file {Path(src).name}, using default emoji..."
60
- )
61
- emoji = self.opt_comp.default_emoji
62
- sticker.emoji = emoji
63
-
64
- if Path(src).suffix == ".webp":
65
- spec_choice = self.webp_spec
66
- else:
67
- spec_choice = self.png_spec
68
-
69
- if not FormatVerify.check_file(src, spec=spec_choice):
70
- if self.opt_comp.fake_vid or CodecInfo.is_anim(src):
71
- dst = "bytes.apng"
72
- else:
73
- dst = "bytes.png"
74
- success, _, image_data, _ = StickerConvert.convert(
75
- Path(src), Path(dst), self.opt_comp_merged, self.cb, self.cb_return
76
- )
77
- if not success:
78
- self.cb.put(
79
- f"Warning: Cannot compress file {Path(src).name}, skip uploading this file..."
80
- )
81
- return None
82
-
83
- assert isinstance(image_data, bytes)
84
-
85
- sticker.image_data = image_data
86
- else:
87
- with open(src, "rb") as f:
88
- sticker.image_data = f.read()
89
-
90
- return sticker
91
-
92
- def add_stickers_to_pack(
93
- self, pack: LocalStickerPack, stickers: List[Path], emoji_dict: Dict[str, str]
94
- ) -> None:
95
- cover_file = MetadataHandler.get_cover(self.opt_output.dir)
96
- cover_file_bytes = None
97
- if cover_file:
98
- with open(cover_file, "rb") as f:
99
- cover_file_bytes = f.read()
100
- for src in stickers:
101
- sticker = self.create_sticker(src, emoji_dict)
102
- if sticker is None:
103
- continue
104
- sticker.id = pack.nb_stickers
105
- pack._addsticker(sticker) # type: ignore
106
-
107
- if (
108
- cover_file
109
- and pack.cover is None
110
- and sticker.image_data == cover_file_bytes
111
- ):
112
- pack.cover = sticker
113
-
114
- if cover_file and pack.cover is None:
115
- sticker = self.create_sticker(cover_file, emoji_dict)
116
- if sticker is not None:
117
- sticker.id = pack.nb_stickers
118
- pack.cover = sticker
119
-
120
- def upload_stickers_signal(self) -> Tuple[int, int, List[str]]:
121
- urls: List[str] = []
122
-
123
- if not self.opt_cred.signal_uuid:
124
- self.cb.put("uuid required for uploading to Signal")
125
- return 0, 0, urls
126
- if not self.opt_cred.signal_password:
127
- self.cb.put("password required for uploading to Signal")
128
- return 0, 0, urls
129
-
130
- title, author, emoji_dict = MetadataHandler.get_metadata(
131
- self.opt_output.dir,
132
- title=self.opt_output.title,
133
- author=self.opt_output.author,
134
- )
135
- if title is None:
136
- raise TypeError(f"title cannot be {title}")
137
- if author is None:
138
- raise TypeError(f"author cannot be {author}")
139
- if emoji_dict is None:
140
- msg_block = "emoji.txt is required for uploading signal stickers\n"
141
- msg_block += f"emoji.txt generated for you in {self.opt_output.dir}\n"
142
- msg_block += f"Default emoji is set to {self.opt_comp.default_emoji}.\n"
143
- msg_block += "Please edit emoji.txt now, then continue"
144
- MetadataHandler.generate_emoji_file(
145
- directory=self.opt_output.dir, default_emoji=self.opt_comp.default_emoji
146
- )
147
-
148
- self.cb.put(("msg_block", (msg_block,), None))
149
- if self.cb_return:
150
- self.cb_return.get_response()
151
-
152
- title, author, emoji_dict = MetadataHandler.get_metadata(
153
- self.opt_output.dir,
154
- title=self.opt_output.title,
155
- author=self.opt_output.author,
156
- )
157
- assert title
158
- assert author
159
- assert emoji_dict
160
-
161
- packs = MetadataHandler.split_sticker_packs(
162
- self.opt_output.dir,
163
- title=title,
164
- file_per_pack=200,
165
- separate_image_anim=False,
166
- )
167
- stickers_total = 0
168
- stickers_ok = 0
169
- for pack_title, stickers in packs.items():
170
- stickers_total += len(stickers)
171
- pack = LocalStickerPack()
172
- pack.title = pack_title
173
- pack.author = author
174
-
175
- self.add_stickers_to_pack(pack, stickers, emoji_dict)
176
- self.cb.put(f"Uploading pack {pack_title}")
177
- self.cb.put("update_bar")
178
- try:
179
- result = anyio.run(
180
- UploadSignal.upload_pack,
181
- pack,
182
- self.opt_cred.signal_uuid,
183
- self.opt_cred.signal_password,
184
- )
185
- self.cb.put((result))
186
- urls.append(result)
187
- stickers_ok += len(stickers)
188
-
189
- except SignalException as e:
190
- self.cb.put(f"Failed to upload pack {pack_title} due to {repr(e)}")
191
-
192
- return stickers_ok, stickers_total, urls
193
-
194
- @staticmethod
195
- def start(
196
- opt_output: OutputOption,
197
- opt_comp: CompOption,
198
- opt_cred: CredOption,
199
- cb: CallbackProtocol,
200
- cb_return: CallbackReturn,
201
- ) -> Tuple[int, int, List[str]]:
202
- exporter = UploadSignal(opt_output, opt_comp, opt_cred, cb, cb_return)
203
- return exporter.upload_stickers_signal()
1
+ #!/usr/bin/env python3
2
+ import copy
3
+ from pathlib import Path
4
+ from typing import Any, Dict, List, Optional, Tuple
5
+
6
+ import anyio
7
+ from signalstickers_client.errors import SignalException
8
+ from signalstickers_client.models import LocalStickerPack, Sticker
9
+ from signalstickers_client.stickersclient import StickersClient
10
+
11
+ from sticker_convert.converter import StickerConvert
12
+ from sticker_convert.job_option import CompOption, CredOption, OutputOption
13
+ from sticker_convert.uploaders.upload_base import UploadBase, get_msg_emoji_txt_required
14
+ from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
15
+ from sticker_convert.utils.emoji import extract_emojis
16
+ from sticker_convert.utils.files.metadata_handler import MetadataHandler
17
+ from sticker_convert.utils.media.codec_info import CodecInfo
18
+ from sticker_convert.utils.media.format_verify import FormatVerify
19
+ from sticker_convert.utils.translate import I
20
+
21
+
22
+ class UploadSignal(UploadBase):
23
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
24
+ super().__init__(*args, **kwargs)
25
+
26
+ self.base_spec.set_size_max(300000)
27
+ self.base_spec.set_res_max(512)
28
+ self.base_spec.duration_max = 3000
29
+
30
+ self.png_spec = copy.deepcopy(self.base_spec)
31
+ self.png_spec.set_format((".apng",))
32
+
33
+ self.webp_spec = copy.deepcopy(self.base_spec)
34
+ self.webp_spec.format_img = (".webp",)
35
+ self.webp_spec.animated = False
36
+
37
+ self.opt_comp_merged = copy.deepcopy(self.opt_comp)
38
+ self.opt_comp_merged.merge(self.base_spec)
39
+
40
+ @staticmethod
41
+ async def upload_pack(pack: LocalStickerPack, uuid: str, password: str) -> str:
42
+ async with StickersClient(uuid, password) as client:
43
+ pack_id, pack_key = await client.upload_pack(pack)
44
+
45
+ result = (
46
+ f"https://signal.art/addstickers/#pack_id={pack_id}&pack_key={pack_key}"
47
+ )
48
+ return result
49
+
50
+ def create_sticker(
51
+ self, src: Path, emoji_dict: Dict[str, str]
52
+ ) -> Optional[Sticker]:
53
+ self.cb.put(I("Verifying {} for uploading to signal").format(src))
54
+
55
+ sticker = Sticker()
56
+
57
+ emoji = extract_emojis(emoji_dict.get(Path(src).stem, ""))
58
+ if emoji == "":
59
+ self.cb.put(
60
+ I(
61
+ "Warning: Cannot find emoji for file {}, using default emoji..."
62
+ ).format(Path(src).name)
63
+ )
64
+ emoji = self.opt_comp.default_emoji
65
+ sticker.emoji = emoji
66
+
67
+ if Path(src).suffix == ".webp":
68
+ spec_choice = self.webp_spec
69
+ else:
70
+ spec_choice = self.png_spec
71
+
72
+ if not FormatVerify.check_file(src, spec=spec_choice):
73
+ if self.opt_comp.fake_vid or CodecInfo.is_anim(src):
74
+ dst = "bytes.apng"
75
+ else:
76
+ dst = "bytes.png"
77
+ success, _, image_data, _ = StickerConvert.convert(
78
+ Path(src), Path(dst), self.opt_comp_merged, self.cb, self.cb_return
79
+ )
80
+ if not success:
81
+ self.cb.put(
82
+ I(
83
+ "Warning: Cannot compress file {}, skip uploading this file..."
84
+ ).format(Path(src).name)
85
+ )
86
+ return None
87
+
88
+ assert isinstance(image_data, bytes)
89
+
90
+ sticker.image_data = image_data
91
+ else:
92
+ with open(src, "rb") as f:
93
+ sticker.image_data = f.read()
94
+
95
+ return sticker
96
+
97
+ def add_stickers_to_pack(
98
+ self, pack: LocalStickerPack, stickers: List[Path], emoji_dict: Dict[str, str]
99
+ ) -> None:
100
+ cover_file = MetadataHandler.get_cover(self.opt_output.dir)
101
+ cover_file_bytes = None
102
+ if cover_file:
103
+ with open(cover_file, "rb") as f:
104
+ cover_file_bytes = f.read()
105
+ for src in stickers:
106
+ sticker = self.create_sticker(src, emoji_dict)
107
+ if sticker is None:
108
+ continue
109
+ sticker.id = pack.nb_stickers
110
+ pack._addsticker(sticker) # type: ignore
111
+
112
+ if (
113
+ cover_file
114
+ and pack.cover is None
115
+ and sticker.image_data == cover_file_bytes
116
+ ):
117
+ pack.cover = sticker
118
+
119
+ if cover_file and pack.cover is None:
120
+ sticker = self.create_sticker(cover_file, emoji_dict)
121
+ if sticker is not None:
122
+ sticker.id = pack.nb_stickers
123
+ pack.cover = sticker
124
+
125
+ def upload_stickers_signal(self) -> Tuple[int, int, List[str]]:
126
+ urls: List[str] = []
127
+
128
+ if not self.opt_cred.signal_uuid:
129
+ self.cb.put(I("uuid required for uploading to Signal"))
130
+ return 0, 0, urls
131
+ if not self.opt_cred.signal_password:
132
+ self.cb.put(I("password required for uploading to Signal"))
133
+ return 0, 0, urls
134
+
135
+ title, author, emoji_dict = MetadataHandler.get_metadata(
136
+ self.opt_output.dir,
137
+ title=self.opt_output.title,
138
+ author=self.opt_output.author,
139
+ )
140
+ if title is None:
141
+ raise TypeError(I("title cannot be {}").format(title))
142
+ if author is None:
143
+ raise TypeError(I("author cannot be {}").format(author))
144
+ if emoji_dict is None:
145
+ MetadataHandler.generate_emoji_file(
146
+ directory=self.opt_output.dir, default_emoji=self.opt_comp.default_emoji
147
+ )
148
+
149
+ self.cb.put(
150
+ (
151
+ "msg_block",
152
+ (
153
+ get_msg_emoji_txt_required().format(
154
+ self.opt_output.dir, self.opt_comp.default_emoji
155
+ ),
156
+ ),
157
+ None,
158
+ )
159
+ )
160
+ if self.cb_return:
161
+ self.cb_return.get_response()
162
+
163
+ title, author, emoji_dict = MetadataHandler.get_metadata(
164
+ self.opt_output.dir,
165
+ title=self.opt_output.title,
166
+ author=self.opt_output.author,
167
+ )
168
+ assert title
169
+ assert author
170
+ assert emoji_dict
171
+
172
+ packs = MetadataHandler.split_sticker_packs(
173
+ self.opt_output.dir,
174
+ title=title,
175
+ file_per_pack=200,
176
+ separate_image_anim=False,
177
+ )
178
+ stickers_total = 0
179
+ stickers_ok = 0
180
+ for pack_title, stickers in packs.items():
181
+ stickers_total += len(stickers)
182
+ pack = LocalStickerPack()
183
+ pack.title = pack_title
184
+ pack.author = author
185
+
186
+ self.add_stickers_to_pack(pack, stickers, emoji_dict)
187
+ self.cb.put(I("Uploading pack {}").format(pack_title))
188
+ self.cb.put("update_bar")
189
+ try:
190
+ result = anyio.run(
191
+ UploadSignal.upload_pack,
192
+ pack,
193
+ self.opt_cred.signal_uuid,
194
+ self.opt_cred.signal_password,
195
+ )
196
+ self.cb.put((result))
197
+ urls.append(result)
198
+ stickers_ok += len(stickers)
199
+
200
+ except SignalException as e:
201
+ self.cb.put(
202
+ I("Failed to upload pack {}. Reason: {}").format(
203
+ pack_title, repr(e)
204
+ )
205
+ )
206
+
207
+ return stickers_ok, stickers_total, urls
208
+
209
+ @staticmethod
210
+ def start(
211
+ opt_output: OutputOption,
212
+ opt_comp: CompOption,
213
+ opt_cred: CredOption,
214
+ cb: CallbackProtocol,
215
+ cb_return: CallbackReturn,
216
+ ) -> Tuple[int, int, List[str]]:
217
+ exporter = UploadSignal(opt_output, opt_comp, opt_cred, cb, cb_return)
218
+ return exporter.upload_stickers_signal()