sticker-convert 2.8.12__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.
- sticker_convert/__main__.py +24 -24
- sticker_convert/auth/__init__.py +0 -0
- sticker_convert/auth/auth_base.py +19 -0
- sticker_convert/auth/auth_discord.py +149 -0
- sticker_convert/{utils/auth/get_kakao_auth.py → auth/auth_kakao_android_login.py} +331 -300
- sticker_convert/auth/auth_kakao_desktop_login.py +327 -0
- sticker_convert/auth/auth_kakao_desktop_memdump.py +281 -0
- sticker_convert/{utils/auth/get_line_auth.py → auth/auth_line.py} +98 -80
- sticker_convert/auth/auth_signal.py +139 -0
- sticker_convert/auth/auth_telethon.py +161 -0
- sticker_convert/auth/auth_viber.py +250 -0
- sticker_convert/auth/telegram_api.py +736 -0
- sticker_convert/cli.py +623 -509
- sticker_convert/converter.py +1093 -962
- sticker_convert/definitions.py +11 -0
- sticker_convert/downloaders/download_band.py +111 -0
- sticker_convert/downloaders/download_base.py +171 -130
- sticker_convert/downloaders/download_discord.py +92 -0
- sticker_convert/downloaders/download_kakao.py +417 -255
- sticker_convert/downloaders/download_line.py +484 -472
- sticker_convert/downloaders/download_ogq.py +80 -0
- sticker_convert/downloaders/download_signal.py +108 -92
- sticker_convert/downloaders/download_telegram.py +56 -130
- sticker_convert/downloaders/download_viber.py +121 -95
- sticker_convert/gui.py +788 -795
- sticker_convert/gui_components/frames/comp_frame.py +180 -165
- sticker_convert/gui_components/frames/config_frame.py +156 -113
- sticker_convert/gui_components/frames/control_frame.py +32 -30
- sticker_convert/gui_components/frames/cred_frame.py +232 -162
- sticker_convert/gui_components/frames/input_frame.py +139 -137
- sticker_convert/gui_components/frames/output_frame.py +112 -110
- sticker_convert/gui_components/frames/right_clicker.py +25 -23
- sticker_convert/gui_components/windows/advanced_compression_window.py +757 -715
- sticker_convert/gui_components/windows/base_window.py +7 -2
- sticker_convert/gui_components/windows/discord_get_auth_window.py +79 -0
- sticker_convert/gui_components/windows/kakao_get_auth_window.py +511 -186
- sticker_convert/gui_components/windows/line_get_auth_window.py +94 -102
- sticker_convert/gui_components/windows/signal_get_auth_window.py +84 -135
- sticker_convert/gui_components/windows/viber_get_auth_window.py +168 -0
- sticker_convert/ios-message-stickers-template/.github/FUNDING.yml +3 -3
- sticker_convert/ios-message-stickers-template/.gitignore +0 -0
- sticker_convert/ios-message-stickers-template/README.md +10 -10
- sticker_convert/ios-message-stickers-template/stickers/Info.plist +43 -43
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Info.plist +31 -31
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Contents.json +6 -6
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Contents.json +20 -20
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Contents.json +9 -9
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 1.sticker/Sticker 1.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Contents.json +9 -9
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 2.sticker/Sticker 2.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Contents.json +9 -9
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/Sticker Pack.stickerpack/Sticker 3.sticker/Sticker 3.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/App-Store-1024x1024pt.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Contents.json +91 -91
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-App-Store-1024x768pt.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-67x50pt@2x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPad-Pro-74x55pt@2x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@2x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages-iPhone-60x45pt@3x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@2x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages27x20pt@3x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@2x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/Messages32x24pt@3x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPad-Settings-29pt@2x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-Settings-29pt@3x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers StickerPackExtension/Stickers.xcstickers/iMessage App Icon.stickersiconset/iPhone-settings-29pt@2x.png +0 -0
- sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.pbxproj +364 -364
- sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -7
- sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -8
- sticker_convert/ios-message-stickers-template/stickers.xcodeproj/project.xcworkspace/xcuserdata/niklaspeterson.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- sticker_convert/ios-message-stickers-template/stickers.xcodeproj/xcuserdata/niklaspeterson.xcuserdatad/xcschemes/xcschememanagement.plist +14 -14
- sticker_convert/job.py +279 -179
- sticker_convert/job_option.py +15 -2
- sticker_convert/locales/en_US/LC_MESSAGES/base.mo +0 -0
- sticker_convert/locales/ja_JP/LC_MESSAGES/base.mo +0 -0
- sticker_convert/locales/zh_CN/LC_MESSAGES/base.mo +0 -0
- sticker_convert/locales/zh_TW/LC_MESSAGES/base.mo +0 -0
- sticker_convert/py.typed +0 -0
- sticker_convert/resources/NotoColorEmoji.ttf +0 -0
- sticker_convert/resources/compression.json +220 -16
- sticker_convert/resources/emoji.json +527 -77
- sticker_convert/resources/help.ja_JP.json +88 -0
- sticker_convert/resources/help.json +24 -10
- sticker_convert/resources/help.zh_CN.json +88 -0
- sticker_convert/resources/help.zh_TW.json +88 -0
- sticker_convert/resources/input.ja_JP.json +74 -0
- sticker_convert/resources/input.json +121 -71
- sticker_convert/resources/input.zh_CN.json +74 -0
- sticker_convert/resources/input.zh_TW.json +74 -0
- sticker_convert/resources/memdump_linux.sh +25 -0
- sticker_convert/resources/memdump_windows.ps1 +8 -0
- sticker_convert/resources/output.ja_JP.json +38 -0
- sticker_convert/resources/output.json +24 -0
- sticker_convert/resources/output.zh_CN.json +38 -0
- sticker_convert/resources/output.zh_TW.json +38 -0
- sticker_convert/uploaders/compress_wastickers.py +186 -156
- sticker_convert/uploaders/upload_base.py +44 -35
- sticker_convert/uploaders/upload_signal.py +218 -173
- sticker_convert/uploaders/upload_telegram.py +353 -388
- sticker_convert/uploaders/upload_viber.py +178 -0
- sticker_convert/uploaders/xcode_imessage.py +295 -285
- sticker_convert/utils/callback.py +238 -6
- sticker_convert/utils/chrome_remotedebug.py +219 -0
- sticker_convert/utils/chromiums/linux.py +52 -0
- sticker_convert/utils/chromiums/osx.py +68 -0
- sticker_convert/utils/chromiums/windows.py +45 -0
- sticker_convert/utils/emoji.py +28 -0
- sticker_convert/utils/files/json_resources_loader.py +24 -19
- sticker_convert/utils/files/metadata_handler.py +8 -7
- sticker_convert/utils/files/run_bin.py +1 -1
- sticker_convert/utils/media/codec_info.py +99 -67
- sticker_convert/utils/media/format_verify.py +33 -20
- sticker_convert/utils/process.py +231 -0
- sticker_convert/utils/translate.py +108 -0
- sticker_convert/utils/url_detect.py +40 -33
- sticker_convert/version.py +1 -1
- {sticker_convert-2.8.12.dist-info → sticker_convert-2.17.0.0.dist-info}/METADATA +189 -96
- sticker_convert-2.17.0.0.dist-info/RECORD +138 -0
- {sticker_convert-2.8.12.dist-info → sticker_convert-2.17.0.0.dist-info}/WHEEL +1 -1
- sticker_convert/utils/auth/get_signal_auth.py +0 -129
- sticker_convert-2.8.12.dist-info/RECORD +0 -101
- {sticker_convert-2.8.12.dist-info → sticker_convert-2.17.0.0.dist-info}/entry_points.txt +0 -0
- {sticker_convert-2.8.12.dist-info → sticker_convert-2.17.0.0.dist-info/licenses}/LICENSE +0 -0
- {sticker_convert-2.8.12.dist-info → sticker_convert-2.17.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,472 +1,484 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
|
|
4
|
-
import json
|
|
5
|
-
import os
|
|
6
|
-
import string
|
|
7
|
-
import zipfile
|
|
8
|
-
from io import BytesIO
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
from typing import Any, Dict, List, Optional, Tuple
|
|
11
|
-
from urllib import parse
|
|
12
|
-
|
|
13
|
-
import requests
|
|
14
|
-
from bs4 import BeautifulSoup
|
|
15
|
-
from PIL import Image
|
|
16
|
-
|
|
17
|
-
from sticker_convert.
|
|
18
|
-
from sticker_convert.
|
|
19
|
-
from sticker_convert.
|
|
20
|
-
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
|
21
|
-
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
|
22
|
-
from sticker_convert.utils.media.apple_png_normalize import ApplePngNormalize
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
"
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
.
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
self.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
self.
|
|
454
|
-
|
|
455
|
-
)
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
self.
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import string
|
|
7
|
+
import zipfile
|
|
8
|
+
from io import BytesIO
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
11
|
+
from urllib import parse
|
|
12
|
+
|
|
13
|
+
import requests
|
|
14
|
+
from bs4 import BeautifulSoup
|
|
15
|
+
from PIL import Image
|
|
16
|
+
|
|
17
|
+
from sticker_convert.auth.auth_line import AuthLine
|
|
18
|
+
from sticker_convert.downloaders.download_base import DownloadBase
|
|
19
|
+
from sticker_convert.job_option import CredOption, InputOption
|
|
20
|
+
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
|
21
|
+
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
|
22
|
+
from sticker_convert.utils.media.apple_png_normalize import ApplePngNormalize
|
|
23
|
+
from sticker_convert.utils.translate import I
|
|
24
|
+
|
|
25
|
+
# Reference: https://github.com/doubleplusc/Line-sticker-downloader/blob/master/sticker_dl.py
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class MetadataLine:
|
|
29
|
+
@staticmethod
|
|
30
|
+
def analyze_url(url: str) -> Optional[Tuple[str, str, bool]]:
|
|
31
|
+
region = ""
|
|
32
|
+
is_emoji = False
|
|
33
|
+
if url.startswith("line://shop/detail/"):
|
|
34
|
+
pack_id = url.replace("line://shop/detail/", "")
|
|
35
|
+
if len(url) == 24 and all(c in string.hexdigits for c in url):
|
|
36
|
+
is_emoji = True
|
|
37
|
+
elif url.startswith("https://store.line.me/stickershop/product/"):
|
|
38
|
+
pack_id = url.replace(
|
|
39
|
+
"https://store.line.me/stickershop/product/", ""
|
|
40
|
+
).split("/")[0]
|
|
41
|
+
region = url.replace(
|
|
42
|
+
"https://store.line.me/stickershop/product/", ""
|
|
43
|
+
).split("/")[1]
|
|
44
|
+
elif url.startswith("https://line.me/S/sticker"):
|
|
45
|
+
url_parsed = parse.urlparse(url)
|
|
46
|
+
pack_id = url.replace("https://line.me/S/sticker/", "").split("/")[0]
|
|
47
|
+
region = parse.parse_qs(url_parsed.query)["lang"][0]
|
|
48
|
+
elif url.startswith("https://store.line.me/officialaccount/event/sticker/"):
|
|
49
|
+
pack_id = url.replace(
|
|
50
|
+
"https://store.line.me/officialaccount/event/sticker/", ""
|
|
51
|
+
).split("/")[0]
|
|
52
|
+
region = url.replace(
|
|
53
|
+
"https://store.line.me/officialaccount/event/sticker/", ""
|
|
54
|
+
).split("/")[1]
|
|
55
|
+
elif url.startswith("https://store.line.me/emojishop/product/"):
|
|
56
|
+
pack_id = url.replace("https://store.line.me/emojishop/product/", "").split(
|
|
57
|
+
"/"
|
|
58
|
+
)[0]
|
|
59
|
+
region = url.replace("https://store.line.me/emojishop/product/", "").split(
|
|
60
|
+
"/"
|
|
61
|
+
)[1]
|
|
62
|
+
is_emoji = True
|
|
63
|
+
elif url.startswith("https://line.me/S/emoji"):
|
|
64
|
+
url_parsed = parse.urlparse(url)
|
|
65
|
+
pack_id = parse.parse_qs(url_parsed.query)["id"][0]
|
|
66
|
+
region = parse.parse_qs(url_parsed.query)["lang"][0]
|
|
67
|
+
is_emoji = True
|
|
68
|
+
elif len(url) == 24 and all(c in string.hexdigits for c in url):
|
|
69
|
+
pack_id = url
|
|
70
|
+
is_emoji = True
|
|
71
|
+
elif url.isnumeric():
|
|
72
|
+
pack_id = url
|
|
73
|
+
else:
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
return pack_id, region, is_emoji
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def get_metadata_sticon(
|
|
80
|
+
pack_id: str, region: str
|
|
81
|
+
) -> Optional[Tuple[str, str, List[Dict[str, Any]], str, bool, bool]]:
|
|
82
|
+
pack_meta_r = requests.get(
|
|
83
|
+
f"https://stickershop.line-scdn.net/sticonshop/v1/{pack_id}/sticon/iphone/meta.json"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
if pack_meta_r.status_code == 200:
|
|
87
|
+
pack_meta = json.loads(pack_meta_r.text)
|
|
88
|
+
else:
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
if region == "":
|
|
92
|
+
region = "en"
|
|
93
|
+
|
|
94
|
+
pack_store_page = requests.get(
|
|
95
|
+
f"https://store.line.me/emojishop/product/{pack_id}/{region}"
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
if pack_store_page.status_code != 200:
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
pack_store_page_soup = BeautifulSoup(pack_store_page.text, "html.parser")
|
|
102
|
+
|
|
103
|
+
title_tag = pack_store_page_soup.find(class_="mdCMN38Item01Txt") # type: ignore
|
|
104
|
+
if title_tag:
|
|
105
|
+
title = title_tag.text
|
|
106
|
+
else:
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
author_tag = pack_store_page_soup.find(class_="mdCMN38Item01Author") # type: ignore
|
|
110
|
+
if author_tag:
|
|
111
|
+
author = author_tag.text
|
|
112
|
+
else:
|
|
113
|
+
return None
|
|
114
|
+
|
|
115
|
+
files = pack_meta["orders"]
|
|
116
|
+
|
|
117
|
+
resource_type = pack_meta.get("sticonResourceType")
|
|
118
|
+
has_animation = True if resource_type == "ANIMATION" else False
|
|
119
|
+
has_sound = False
|
|
120
|
+
|
|
121
|
+
return title, author, files, resource_type, has_animation, has_sound
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def get_metadata_stickers(
|
|
125
|
+
pack_id: str, region: str
|
|
126
|
+
) -> Optional[Tuple[str, str, List[Dict[str, Any]], str, bool, bool]]:
|
|
127
|
+
pack_meta_r = requests.get(
|
|
128
|
+
f"https://stickershop.line-scdn.net/stickershop/v1/product/{pack_id}/android/productInfo.meta"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
if pack_meta_r.status_code == 200:
|
|
132
|
+
pack_meta = json.loads(pack_meta_r.text)
|
|
133
|
+
else:
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
if region == "":
|
|
137
|
+
if "en" in pack_meta["title"]:
|
|
138
|
+
# Prefer en release
|
|
139
|
+
region = "en"
|
|
140
|
+
else:
|
|
141
|
+
# If no en release, use whatever comes first
|
|
142
|
+
region = pack_meta["title"].keys()[0]
|
|
143
|
+
|
|
144
|
+
if region == "zh-Hant":
|
|
145
|
+
region = "zh_TW"
|
|
146
|
+
|
|
147
|
+
title = pack_meta["title"].get("en")
|
|
148
|
+
if title is None:
|
|
149
|
+
title = pack_meta["title"][region]
|
|
150
|
+
|
|
151
|
+
author = pack_meta["author"].get("en")
|
|
152
|
+
if author is None:
|
|
153
|
+
author = pack_meta["author"][region]
|
|
154
|
+
|
|
155
|
+
files = pack_meta["stickers"]
|
|
156
|
+
|
|
157
|
+
resource_type = pack_meta.get("stickerResourceType")
|
|
158
|
+
has_animation = pack_meta.get("hasAnimation")
|
|
159
|
+
has_sound = pack_meta.get("hasSound")
|
|
160
|
+
|
|
161
|
+
return title, author, files, resource_type, has_animation, has_sound
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class DownloadLine(DownloadBase):
|
|
165
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
166
|
+
self.MSG_CUSTOM_TEXT = I(
|
|
167
|
+
"The Line sticker pack you are downloading can have customized text.\n"
|
|
168
|
+
"line-sticker-text.txt has been created in input directory.\n"
|
|
169
|
+
"Please edit line-sticker-text.txt, then continue."
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
super().__init__(*args, **kwargs)
|
|
173
|
+
self.headers = {
|
|
174
|
+
"referer": "https://store.line.me",
|
|
175
|
+
"user-agent": "Android",
|
|
176
|
+
"x-requested-with": "XMLHttpRequest",
|
|
177
|
+
}
|
|
178
|
+
self.cookies = self.load_cookies()
|
|
179
|
+
self.sticker_text_dict: Dict[int, Any] = {}
|
|
180
|
+
|
|
181
|
+
def load_cookies(self) -> Dict[str, str]:
|
|
182
|
+
cookies: Dict[str, str] = {}
|
|
183
|
+
if self.opt_cred and self.opt_cred.line_cookies:
|
|
184
|
+
line_cookies = self.opt_cred.line_cookies
|
|
185
|
+
|
|
186
|
+
try:
|
|
187
|
+
line_cookies_dict = json.loads(line_cookies)
|
|
188
|
+
for c in line_cookies_dict:
|
|
189
|
+
cookies[c["name"]] = c["value"]
|
|
190
|
+
except json.decoder.JSONDecodeError:
|
|
191
|
+
try:
|
|
192
|
+
for i in line_cookies.split(";"):
|
|
193
|
+
c_key, c_value = i.split("=")
|
|
194
|
+
cookies[c_key] = c_value
|
|
195
|
+
except ValueError:
|
|
196
|
+
self.cb.put(
|
|
197
|
+
I(
|
|
198
|
+
'Warning: Line cookies invalid, you will not be able to add text to "Custom stickers"'
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
if not AuthLine.validate_cookies(cookies):
|
|
203
|
+
self.cb.put(
|
|
204
|
+
I(
|
|
205
|
+
'Warning: Line cookies invalid, you will not be able to add text to "Custom stickers"'
|
|
206
|
+
)
|
|
207
|
+
)
|
|
208
|
+
cookies = {}
|
|
209
|
+
|
|
210
|
+
return cookies
|
|
211
|
+
|
|
212
|
+
def get_pack_url(self) -> str:
|
|
213
|
+
# Reference: https://sora.vercel.app/line-sticker-download
|
|
214
|
+
if self.is_emoji:
|
|
215
|
+
if self.resource_type == "ANIMATION":
|
|
216
|
+
pack_url = f"https://stickershop.line-scdn.net/sticonshop/v1/{self.pack_id}/sticon/iphone/package_animation.zip"
|
|
217
|
+
else:
|
|
218
|
+
pack_url = f"https://stickershop.line-scdn.net/sticonshop/v1/{self.pack_id}/sticon/iphone/package.zip"
|
|
219
|
+
else:
|
|
220
|
+
if (
|
|
221
|
+
self.resource_type in ("ANIMATION", "ANIMATION_SOUND", "POPUP")
|
|
222
|
+
or self.has_sound is True
|
|
223
|
+
or self.has_animation is True
|
|
224
|
+
):
|
|
225
|
+
pack_url = f"https://stickershop.line-scdn.net/stickershop/v1/product/{self.pack_id}/iphone/stickerpack@2x.zip"
|
|
226
|
+
elif self.resource_type == "PER_STICKER_TEXT":
|
|
227
|
+
pack_url = f"https://stickershop.line-scdn.net/stickershop/v1/product/{self.pack_id}/iphone/sticker_custom_plus_base@2x.zip"
|
|
228
|
+
elif self.resource_type == "NAME_TEXT":
|
|
229
|
+
pack_url = f"https://stickershop.line-scdn.net/stickershop/v1/product/{self.pack_id}/iphone/sticker_name_base@2x.zip"
|
|
230
|
+
else:
|
|
231
|
+
pack_url = f"https://stickershop.line-scdn.net/stickershop/v1/product/{self.pack_id}/iphone/stickers@2x.zip"
|
|
232
|
+
|
|
233
|
+
return pack_url
|
|
234
|
+
|
|
235
|
+
def decompress(
|
|
236
|
+
self,
|
|
237
|
+
zf: zipfile.ZipFile,
|
|
238
|
+
f_path: str,
|
|
239
|
+
num: int,
|
|
240
|
+
prefix: str = "",
|
|
241
|
+
suffix: str = "",
|
|
242
|
+
) -> None:
|
|
243
|
+
data = zf.read(f_path)
|
|
244
|
+
ext = Path(f_path).suffix
|
|
245
|
+
if ext == ".png" and not self.is_emoji and int() < 775:
|
|
246
|
+
data = ApplePngNormalize.normalize(data)
|
|
247
|
+
self.cb.put(I("Read {}").format(f_path))
|
|
248
|
+
|
|
249
|
+
out_path = Path(self.out_dir, prefix + str(num).zfill(3) + suffix + ext)
|
|
250
|
+
with open(out_path, "wb") as f:
|
|
251
|
+
f.write(data)
|
|
252
|
+
|
|
253
|
+
def decompress_emoticon(self, zip_file: bytes) -> None:
|
|
254
|
+
with zipfile.ZipFile(BytesIO(zip_file)) as zf:
|
|
255
|
+
self.cb.put(I("Unzipping..."))
|
|
256
|
+
|
|
257
|
+
self.cb.put(
|
|
258
|
+
(
|
|
259
|
+
"bar",
|
|
260
|
+
None,
|
|
261
|
+
{"set_progress_mode": "determinate", "steps": len(self.pack_files)},
|
|
262
|
+
)
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
for num, sticker in enumerate(self.pack_files):
|
|
266
|
+
if self.has_animation is True:
|
|
267
|
+
f_path = str(sticker) + "_animation.png"
|
|
268
|
+
else:
|
|
269
|
+
f_path = str(sticker) + ".png"
|
|
270
|
+
self.decompress(zf, f_path, num)
|
|
271
|
+
|
|
272
|
+
self.cb.put("update_bar")
|
|
273
|
+
|
|
274
|
+
def decompress_stickers(self, zip_file: bytes) -> None:
|
|
275
|
+
with zipfile.ZipFile(BytesIO(zip_file)) as zf:
|
|
276
|
+
self.cb.put(I("Unzipping..."))
|
|
277
|
+
|
|
278
|
+
self.cb.put(
|
|
279
|
+
(
|
|
280
|
+
"bar",
|
|
281
|
+
None,
|
|
282
|
+
{"set_progress_mode": "determinate", "steps": len(self.pack_files)},
|
|
283
|
+
)
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
for num, sticker in enumerate(self.pack_files):
|
|
287
|
+
if self.resource_type == "POPUP":
|
|
288
|
+
if sticker.get("popup", {}).get("layer") == "BACKGROUND":
|
|
289
|
+
f_path = str(sticker["id"]) + "@2x.png"
|
|
290
|
+
self.decompress(zf, f_path, num, "preview-")
|
|
291
|
+
f_path = "popup/" + str(sticker["id"]) + ".png"
|
|
292
|
+
elif self.has_animation is True:
|
|
293
|
+
f_path = "animation@2x/" + str(sticker["id"]) + "@2x.png"
|
|
294
|
+
else:
|
|
295
|
+
f_path = str(sticker["id"]) + "@2x.png"
|
|
296
|
+
self.decompress(zf, f_path, num)
|
|
297
|
+
|
|
298
|
+
if self.resource_type == "PER_STICKER_TEXT":
|
|
299
|
+
self.sticker_text_dict[num] = {
|
|
300
|
+
"sticker_id": sticker["id"],
|
|
301
|
+
"sticker_text": sticker["customPlus"]["defaultText"],
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
elif self.resource_type == "NAME_TEXT":
|
|
305
|
+
self.sticker_text_dict[num] = {
|
|
306
|
+
"sticker_id": sticker["id"],
|
|
307
|
+
"sticker_text": "",
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if self.has_sound:
|
|
311
|
+
f_path = "sound/" + str(sticker["id"]) + ".m4a"
|
|
312
|
+
self.decompress(zf, f_path, num)
|
|
313
|
+
|
|
314
|
+
self.cb.put("update_bar")
|
|
315
|
+
|
|
316
|
+
def edit_custom_sticker_text(self) -> None:
|
|
317
|
+
line_sticker_text_path = Path(self.out_dir, "line-sticker-text.txt")
|
|
318
|
+
|
|
319
|
+
if not line_sticker_text_path.is_file():
|
|
320
|
+
with open(line_sticker_text_path, "w+", encoding="utf-8") as f:
|
|
321
|
+
json.dump(self.sticker_text_dict, f, indent=4, ensure_ascii=False)
|
|
322
|
+
self.cb.put(("msg_block", (self.MSG_CUSTOM_TEXT,), None))
|
|
323
|
+
if self.cb_return:
|
|
324
|
+
self.cb_return.get_response()
|
|
325
|
+
|
|
326
|
+
with open(line_sticker_text_path, "r", encoding="utf-8") as f:
|
|
327
|
+
self.sticker_text_dict = json.load(f)
|
|
328
|
+
|
|
329
|
+
def get_custom_sticker_text_urls(self) -> List[Tuple[str, Path]]:
|
|
330
|
+
custom_sticker_text_urls: List[Tuple[str, Path]] = []
|
|
331
|
+
name_text_key_cache: Dict[str, str] = {}
|
|
332
|
+
|
|
333
|
+
for num, data in self.sticker_text_dict.items():
|
|
334
|
+
out_path = Path(self.out_dir, str(num).zfill(3))
|
|
335
|
+
sticker_id = data["sticker_id"]
|
|
336
|
+
sticker_text = data["sticker_text"]
|
|
337
|
+
|
|
338
|
+
if self.resource_type == "PER_STICKER_TEXT":
|
|
339
|
+
out_path_text = out_path.with_name(out_path.name + "-text.png")
|
|
340
|
+
custom_sticker_text_urls.append(
|
|
341
|
+
(
|
|
342
|
+
f"https://store.line.me/overlay/sticker/{self.pack_id}/{sticker_id}/iPhone/sticker.png?text={parse.quote(sticker_text)}",
|
|
343
|
+
out_path_text,
|
|
344
|
+
)
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
elif self.resource_type == "NAME_TEXT" and sticker_text:
|
|
348
|
+
out_path_text = out_path.with_name(out_path.name + "-text.png")
|
|
349
|
+
name_text_key = name_text_key_cache.get(sticker_text, None)
|
|
350
|
+
if not name_text_key:
|
|
351
|
+
name_text_key = self.get_name_text_key(sticker_text)
|
|
352
|
+
if name_text_key:
|
|
353
|
+
name_text_key_cache[sticker_text] = name_text_key
|
|
354
|
+
else:
|
|
355
|
+
continue
|
|
356
|
+
|
|
357
|
+
custom_sticker_text_urls.append(
|
|
358
|
+
(
|
|
359
|
+
f"https://stickershop.line-scdn.net/stickershop/v1/sticker/{sticker_id}/iPhone/overlay/name/{name_text_key}/sticker@2x.png",
|
|
360
|
+
out_path_text,
|
|
361
|
+
)
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
return custom_sticker_text_urls
|
|
365
|
+
|
|
366
|
+
def get_name_text_key(self, sticker_text: str) -> Optional[str]:
|
|
367
|
+
params = {"text": sticker_text}
|
|
368
|
+
|
|
369
|
+
response = requests.get(
|
|
370
|
+
f"https://store.line.me/api/custom-sticker/preview/{self.pack_id}/{self.region}",
|
|
371
|
+
params=params,
|
|
372
|
+
cookies=self.cookies,
|
|
373
|
+
headers=self.headers,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
response_dict = json.loads(response.text)
|
|
377
|
+
|
|
378
|
+
if response_dict["errorMessage"]:
|
|
379
|
+
self.cb.put(
|
|
380
|
+
I("Failed to generate customized text {} due to: {}").format(
|
|
381
|
+
sticker_text, response_dict["errorMessage"]
|
|
382
|
+
)
|
|
383
|
+
)
|
|
384
|
+
return None
|
|
385
|
+
|
|
386
|
+
name_text_key = (
|
|
387
|
+
response_dict["productPayload"]["customOverlayUrl"]
|
|
388
|
+
.split("name/")[-1]
|
|
389
|
+
.split("/main.png")[0]
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
return name_text_key
|
|
393
|
+
|
|
394
|
+
def combine_custom_text(self) -> None:
|
|
395
|
+
for i in sorted(self.out_dir.iterdir()):
|
|
396
|
+
if i.name.endswith("-text.png"):
|
|
397
|
+
base_path = Path(self.out_dir, i.name.replace("-text.png", ".png"))
|
|
398
|
+
text_path = Path(self.out_dir, i.name)
|
|
399
|
+
|
|
400
|
+
with Image.open(base_path) as im:
|
|
401
|
+
base_img: Image.Image = im.convert("RGBA")
|
|
402
|
+
|
|
403
|
+
with Image.open(text_path) as im:
|
|
404
|
+
text_img = im.convert("RGBA")
|
|
405
|
+
|
|
406
|
+
with Image.alpha_composite(base_img, text_img) as im:
|
|
407
|
+
im.save(base_path)
|
|
408
|
+
|
|
409
|
+
os.remove(text_path)
|
|
410
|
+
|
|
411
|
+
self.cb.put(
|
|
412
|
+
I("Combined {}").format(i.name.replace("-text.png", ".png"))
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
def download_stickers_line(self) -> Tuple[int, int]:
|
|
416
|
+
url_data = MetadataLine.analyze_url(self.url)
|
|
417
|
+
if url_data:
|
|
418
|
+
self.pack_id, self.region, self.is_emoji = url_data
|
|
419
|
+
else:
|
|
420
|
+
self.cb.put(I("Download failed: Unsupported URL format"))
|
|
421
|
+
return 0, 0
|
|
422
|
+
|
|
423
|
+
if self.is_emoji:
|
|
424
|
+
metadata = MetadataLine.get_metadata_sticon(self.pack_id, self.region)
|
|
425
|
+
else:
|
|
426
|
+
metadata = MetadataLine.get_metadata_stickers(self.pack_id, self.region)
|
|
427
|
+
|
|
428
|
+
if metadata:
|
|
429
|
+
(
|
|
430
|
+
self.title,
|
|
431
|
+
self.author,
|
|
432
|
+
self.pack_files,
|
|
433
|
+
self.resource_type,
|
|
434
|
+
self.has_animation,
|
|
435
|
+
self.has_sound,
|
|
436
|
+
) = metadata
|
|
437
|
+
else:
|
|
438
|
+
self.cb.put(I("Download failed: Failed to get metadata"))
|
|
439
|
+
return 0, 0
|
|
440
|
+
|
|
441
|
+
MetadataHandler.set_metadata(self.out_dir, title=self.title, author=self.author)
|
|
442
|
+
|
|
443
|
+
pack_url = self.get_pack_url()
|
|
444
|
+
zip_file = self.download_file(pack_url)
|
|
445
|
+
|
|
446
|
+
if zip_file:
|
|
447
|
+
self.cb.put(I("Downloaded {}").format(pack_url))
|
|
448
|
+
else:
|
|
449
|
+
self.cb.put(I("Cannot download {}").format(pack_url))
|
|
450
|
+
return 0, 0
|
|
451
|
+
|
|
452
|
+
if self.is_emoji:
|
|
453
|
+
self.decompress_emoticon(zip_file)
|
|
454
|
+
else:
|
|
455
|
+
self.decompress_stickers(zip_file)
|
|
456
|
+
|
|
457
|
+
custom_sticker_text_urls: List[Tuple[str, Path]] = []
|
|
458
|
+
if self.sticker_text_dict and (
|
|
459
|
+
self.resource_type == "PER_STICKER_TEXT"
|
|
460
|
+
or (self.resource_type == "NAME_TEXT" and self.cookies)
|
|
461
|
+
):
|
|
462
|
+
self.edit_custom_sticker_text()
|
|
463
|
+
custom_sticker_text_urls = self.get_custom_sticker_text_urls()
|
|
464
|
+
elif self.resource_type == "NAME_TEXT" and not self.cookies:
|
|
465
|
+
self.cb.put('Warning: Line "Custom stickers" is supplied as input')
|
|
466
|
+
self.cb.put(
|
|
467
|
+
"However, adding custom message requires Line cookies, and it is not supplied"
|
|
468
|
+
)
|
|
469
|
+
self.cb.put("Continuing without adding custom text to stickers")
|
|
470
|
+
|
|
471
|
+
self.download_multiple_files(custom_sticker_text_urls, headers=self.headers)
|
|
472
|
+
self.combine_custom_text()
|
|
473
|
+
|
|
474
|
+
return len(self.pack_files), len(self.pack_files)
|
|
475
|
+
|
|
476
|
+
@staticmethod
|
|
477
|
+
def start(
|
|
478
|
+
opt_input: InputOption,
|
|
479
|
+
opt_cred: Optional[CredOption],
|
|
480
|
+
cb: CallbackProtocol,
|
|
481
|
+
cb_return: CallbackReturn,
|
|
482
|
+
) -> Tuple[int, int]:
|
|
483
|
+
downloader = DownloadLine(opt_input, opt_cred, cb, cb_return)
|
|
484
|
+
return downloader.download_stickers_line()
|