sticker-convert 2.8.0__py3-none-any.whl → 2.8.2__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/cli.py +4 -0
- sticker_convert/converter.py +8 -8
- sticker_convert/downloaders/download_base.py +3 -7
- sticker_convert/downloaders/download_kakao.py +3 -4
- sticker_convert/downloaders/download_line.py +3 -4
- sticker_convert/downloaders/download_signal.py +3 -4
- sticker_convert/downloaders/download_telegram.py +3 -4
- sticker_convert/gui.py +3 -1
- sticker_convert/gui_components/windows/advanced_compression_window.py +117 -101
- sticker_convert/job.py +81 -89
- sticker_convert/job_option.py +3 -0
- sticker_convert/resources/compression.json +11 -0
- sticker_convert/resources/help.json +1 -0
- sticker_convert/uploaders/compress_wastickers.py +3 -4
- sticker_convert/uploaders/upload_base.py +2 -8
- sticker_convert/uploaders/upload_signal.py +3 -4
- sticker_convert/uploaders/upload_telegram.py +3 -4
- sticker_convert/uploaders/xcode_imessage.py +3 -4
- sticker_convert/utils/callback.py +33 -21
- sticker_convert/utils/media/codec_info.py +3 -7
- sticker_convert/version.py +1 -1
- {sticker_convert-2.8.0.dist-info → sticker_convert-2.8.2.dist-info}/METADATA +18 -15
- {sticker_convert-2.8.0.dist-info → sticker_convert-2.8.2.dist-info}/RECORD +27 -27
- {sticker_convert-2.8.0.dist-info → sticker_convert-2.8.2.dist-info}/LICENSE +0 -0
- {sticker_convert-2.8.0.dist-info → sticker_convert-2.8.2.dist-info}/WHEEL +0 -0
- {sticker_convert-2.8.0.dist-info → sticker_convert-2.8.2.dist-info}/entry_points.txt +0 -0
- {sticker_convert-2.8.0.dist-info → sticker_convert-2.8.2.dist-info}/top_level.txt +0 -0
sticker_convert/job.py
CHANGED
@@ -5,12 +5,10 @@ import os
|
|
5
5
|
import shutil
|
6
6
|
import traceback
|
7
7
|
from datetime import datetime
|
8
|
-
from multiprocessing import Process, Value
|
9
|
-
from multiprocessing.managers import ListProxy, SyncManager
|
8
|
+
from multiprocessing import Manager, Process, Value
|
10
9
|
from pathlib import Path
|
11
|
-
from queue import Queue
|
12
10
|
from threading import Thread
|
13
|
-
from typing import
|
11
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple
|
14
12
|
from urllib.parse import urlparse
|
15
13
|
|
16
14
|
from sticker_convert.converter import StickerConvert
|
@@ -23,18 +21,11 @@ from sticker_convert.uploaders.compress_wastickers import CompressWastickers
|
|
23
21
|
from sticker_convert.uploaders.upload_signal import UploadSignal
|
24
22
|
from sticker_convert.uploaders.upload_telegram import UploadTelegram
|
25
23
|
from sticker_convert.uploaders.xcode_imessage import XcodeImessage
|
26
|
-
from sticker_convert.utils.callback import CallbackReturn,
|
24
|
+
from sticker_convert.utils.callback import CallbackReturn, CbQueueType, ResultsListType, WorkQueueType
|
27
25
|
from sticker_convert.utils.files.json_resources_loader import OUTPUT_JSON
|
28
26
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
29
27
|
from sticker_convert.utils.media.codec_info import CodecInfo
|
30
28
|
|
31
|
-
WorkListItemType = Optional[Tuple[Callable[..., Any], Tuple[Any, ...]]]
|
32
|
-
if TYPE_CHECKING:
|
33
|
-
# mypy complains about this
|
34
|
-
WorkListType = ListProxy[WorkListItemType] # type: ignore
|
35
|
-
else:
|
36
|
-
WorkListType = List[WorkListItemType]
|
37
|
-
|
38
29
|
|
39
30
|
class Executor:
|
40
31
|
def __init__(
|
@@ -51,33 +42,29 @@ class Executor:
|
|
51
42
|
self.cb_ask_bool = cb_ask_bool
|
52
43
|
self.cb_ask_str = cb_ask_str
|
53
44
|
|
54
|
-
self.manager =
|
55
|
-
self.manager.
|
56
|
-
|
57
|
-
|
58
|
-
self.
|
59
|
-
self.results_queue: Queue[Any] = self.manager.Queue()
|
60
|
-
self.cb_queue: Queue[CbQueueItemType] = self.manager.Queue()
|
61
|
-
self.cb_return = CallbackReturn()
|
45
|
+
self.manager = Manager()
|
46
|
+
self.work_queue: WorkQueueType = self.manager.Queue()
|
47
|
+
self.cb_queue: CbQueueType = self.manager.Queue()
|
48
|
+
self.results_list: ResultsListType = self.manager.list()
|
49
|
+
self.cb_return = CallbackReturn(self.manager)
|
62
50
|
self.processes: List[Process] = []
|
63
51
|
|
64
52
|
self.is_cancel_job = Value("i", 0)
|
65
53
|
|
66
|
-
self.cb_thread_instance =
|
67
|
-
target=self.cb_thread,
|
68
|
-
args=(
|
69
|
-
self.cb_queue,
|
70
|
-
self.cb_return,
|
71
|
-
),
|
72
|
-
)
|
73
|
-
self.cb_thread_instance.start()
|
54
|
+
self.cb_thread_instance: Optional[Thread] = None
|
74
55
|
|
75
56
|
def cb_thread(
|
76
57
|
self,
|
77
|
-
cb_queue:
|
78
|
-
|
58
|
+
cb_queue: CbQueueType,
|
59
|
+
processes: int,
|
79
60
|
) -> None:
|
61
|
+
processes_done = 0
|
80
62
|
for i in iter(cb_queue.get, None):
|
63
|
+
if i == "__PROCESS_DONE__":
|
64
|
+
processes_done += 1
|
65
|
+
if processes_done == processes:
|
66
|
+
cb_queue.put(None)
|
67
|
+
continue
|
81
68
|
if isinstance(i, tuple):
|
82
69
|
action = i[0]
|
83
70
|
if len(i) >= 2:
|
@@ -92,42 +79,44 @@ class Executor:
|
|
92
79
|
action = i
|
93
80
|
args = tuple()
|
94
81
|
kwargs = {}
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
82
|
+
self.cb(action, args, kwargs)
|
83
|
+
|
84
|
+
def cb(
|
85
|
+
self,
|
86
|
+
action: Optional[str],
|
87
|
+
args: Optional[Tuple[str, ...]] = None,
|
88
|
+
kwargs: Optional[Dict[str, Any]] = None,
|
89
|
+
) -> None:
|
90
|
+
if args is None:
|
91
|
+
args = tuple()
|
92
|
+
if kwargs is None:
|
93
|
+
kwargs = {}
|
94
|
+
if action == "msg":
|
95
|
+
self.cb_msg(*args, **kwargs)
|
96
|
+
elif action == "bar":
|
97
|
+
self.cb_bar(*args, **kwargs)
|
98
|
+
elif action == "update_bar":
|
99
|
+
self.cb_bar(update_bar=1)
|
100
|
+
elif action == "msg_block":
|
101
|
+
self.cb_return.set_response(self.cb_msg_block(*args, **kwargs))
|
102
|
+
elif action == "ask_bool":
|
103
|
+
self.cb_return.set_response(self.cb_ask_bool(*args, **kwargs))
|
104
|
+
elif action == "ask_str":
|
105
|
+
self.cb_return.set_response(self.cb_ask_str(*args, **kwargs))
|
106
|
+
else:
|
107
|
+
self.cb_msg(action)
|
109
108
|
|
110
109
|
@staticmethod
|
111
110
|
def worker(
|
112
|
-
|
113
|
-
|
114
|
-
cb_queue:
|
111
|
+
work_queue: WorkQueueType,
|
112
|
+
results_list: ResultsListType,
|
113
|
+
cb_queue: CbQueueType,
|
115
114
|
cb_return: CallbackReturn,
|
116
115
|
) -> None:
|
117
|
-
|
118
|
-
try:
|
119
|
-
work = work_list.pop(0)
|
120
|
-
except IndexError:
|
121
|
-
break
|
122
|
-
|
123
|
-
if work is None:
|
124
|
-
break
|
125
|
-
else:
|
126
|
-
work_func, work_args = work
|
127
|
-
|
116
|
+
for work_func, work_args in iter(work_queue.get, None):
|
128
117
|
try:
|
129
118
|
results = work_func(*work_args, cb_queue, cb_return)
|
130
|
-
|
119
|
+
results_list.append(results)
|
131
120
|
except Exception:
|
132
121
|
arg_dump: List[Any] = []
|
133
122
|
for i in work_args:
|
@@ -142,15 +131,25 @@ class Executor:
|
|
142
131
|
e += "#####################"
|
143
132
|
cb_queue.put(e)
|
144
133
|
|
145
|
-
|
134
|
+
work_queue.put(None)
|
135
|
+
cb_queue.put("__PROCESS_DONE__")
|
146
136
|
|
147
137
|
def start_workers(self, processes: int = 1) -> None:
|
138
|
+
self.cb_thread_instance = Thread(
|
139
|
+
target=self.cb_thread,
|
140
|
+
args=(self.cb_queue, processes),
|
141
|
+
)
|
142
|
+
self.cb_thread_instance.start()
|
143
|
+
|
144
|
+
self.results_list[:] = []
|
145
|
+
while not self.work_queue.empty():
|
146
|
+
self.work_queue.get()
|
148
147
|
for _ in range(processes):
|
149
148
|
process = Process(
|
150
149
|
target=Executor.worker,
|
151
150
|
args=(
|
152
|
-
self.
|
153
|
-
self.
|
151
|
+
self.work_queue,
|
152
|
+
self.results_list,
|
154
153
|
self.cb_queue,
|
155
154
|
self.cb_return,
|
156
155
|
),
|
@@ -163,18 +162,16 @@ class Executor:
|
|
163
162
|
def add_work(
|
164
163
|
self, work_func: Callable[..., Any], work_args: Tuple[Any, ...]
|
165
164
|
) -> None:
|
166
|
-
self.
|
165
|
+
self.work_queue.put((work_func, work_args))
|
167
166
|
|
168
167
|
def join_workers(self) -> None:
|
169
|
-
self.
|
168
|
+
self.work_queue.put(None)
|
170
169
|
try:
|
171
170
|
for process in self.processes:
|
172
171
|
process.join()
|
173
172
|
except KeyboardInterrupt:
|
174
173
|
pass
|
175
174
|
|
176
|
-
self.results_queue.put(None)
|
177
|
-
self.work_list[:] = []
|
178
175
|
self.processes.clear()
|
179
176
|
|
180
177
|
def kill_workers(self, *_: Any, **__: Any) -> None:
|
@@ -183,25 +180,14 @@ class Executor:
|
|
183
180
|
for process in self.processes:
|
184
181
|
process.terminate()
|
185
182
|
|
186
|
-
self.
|
183
|
+
self.cb_msg("Job cancelled.")
|
184
|
+
self.cleanup()
|
187
185
|
|
188
|
-
def cleanup(self
|
189
|
-
|
190
|
-
self.cb_queue.put("Job cancelled.")
|
191
|
-
self.cb_queue.put(("bar", None, {"set_progress_mode": "clear"}))
|
186
|
+
def cleanup(self) -> None:
|
187
|
+
self.cb_bar("clear")
|
192
188
|
self.cb_queue.put(None)
|
193
|
-
self.cb_thread_instance
|
194
|
-
|
195
|
-
def get_result(self) -> Generator[Any, None, None]:
|
196
|
-
yield from iter(self.results_queue.get, None)
|
197
|
-
|
198
|
-
def cb(
|
199
|
-
self,
|
200
|
-
action: Optional[str],
|
201
|
-
args: Optional[Tuple[str, ...]] = None,
|
202
|
-
kwargs: Optional[Dict[str, Any]] = None,
|
203
|
-
) -> None:
|
204
|
-
self.cb_queue.put((action, args, kwargs))
|
189
|
+
if self.cb_thread_instance:
|
190
|
+
self.cb_thread_instance.join()
|
205
191
|
|
206
192
|
|
207
193
|
class Job:
|
@@ -547,17 +533,18 @@ class Job:
|
|
547
533
|
self.executor.cb("Nothing to download")
|
548
534
|
return True
|
549
535
|
|
536
|
+
self.executor.start_workers(processes=1)
|
537
|
+
|
550
538
|
for downloader in downloaders:
|
551
539
|
self.executor.add_work(
|
552
540
|
work_func=downloader,
|
553
541
|
work_args=(self.opt_input.url, self.opt_input.dir, self.opt_cred),
|
554
542
|
)
|
555
543
|
|
556
|
-
self.executor.start_workers(processes=1)
|
557
544
|
self.executor.join_workers()
|
558
545
|
|
559
546
|
# Return False if any of the job returns failure
|
560
|
-
for result in self.executor.
|
547
|
+
for result in self.executor.results_list:
|
561
548
|
if result is False:
|
562
549
|
return False
|
563
550
|
|
@@ -613,12 +600,17 @@ class Job:
|
|
613
600
|
in_fs.append(i)
|
614
601
|
|
615
602
|
in_fs_count = len(in_fs)
|
603
|
+
if in_fs_count == 0:
|
604
|
+
self.executor.cb("No files to compress")
|
605
|
+
return True
|
616
606
|
|
617
607
|
self.executor.cb(msg)
|
618
608
|
self.executor.cb(
|
619
609
|
"bar", kwargs={"set_progress_mode": "determinate", "steps": in_fs_count}
|
620
610
|
)
|
621
611
|
|
612
|
+
self.executor.start_workers(processes=min(self.opt_comp.processes, in_fs_count))
|
613
|
+
|
622
614
|
for i in in_fs:
|
623
615
|
in_f = input_dir / i.name
|
624
616
|
out_f = output_dir / Path(i).stem
|
@@ -627,11 +619,10 @@ class Job:
|
|
627
619
|
work_func=StickerConvert.convert, work_args=(in_f, out_f, self.opt_comp)
|
628
620
|
)
|
629
621
|
|
630
|
-
self.executor.start_workers(processes=min(self.opt_comp.processes, in_fs_count))
|
631
622
|
self.executor.join_workers()
|
632
623
|
|
633
624
|
# Return False if any of the job returns failure
|
634
|
-
for result in self.executor.
|
625
|
+
for result in self.executor.results_list:
|
635
626
|
if result[0] is False:
|
636
627
|
return False
|
637
628
|
|
@@ -661,16 +652,17 @@ class Job:
|
|
661
652
|
if self.opt_output.option == "imessage":
|
662
653
|
exporters.append(XcodeImessage.start)
|
663
654
|
|
655
|
+
self.executor.start_workers(processes=1)
|
656
|
+
|
664
657
|
for exporter in exporters:
|
665
658
|
self.executor.add_work(
|
666
659
|
work_func=exporter,
|
667
660
|
work_args=(self.opt_output, self.opt_comp, self.opt_cred),
|
668
661
|
)
|
669
662
|
|
670
|
-
self.executor.start_workers(processes=1)
|
671
663
|
self.executor.join_workers()
|
672
664
|
|
673
|
-
for result in self.executor.
|
665
|
+
for result in self.executor.results_list:
|
674
666
|
self.out_urls.extend(result)
|
675
667
|
|
676
668
|
if self.out_urls:
|
sticker_convert/job_option.py
CHANGED
@@ -69,6 +69,8 @@ class CompOption(BaseOption):
|
|
69
69
|
|
70
70
|
bg_color: Optional[str] = None
|
71
71
|
|
72
|
+
padding_percent: int = 0
|
73
|
+
|
72
74
|
steps: int = 1
|
73
75
|
fake_vid: Optional[bool] = None
|
74
76
|
quantize_method: Optional[str] = None
|
@@ -104,6 +106,7 @@ class CompOption(BaseOption):
|
|
104
106
|
"duration": {"min": self.duration_min, "max": self.duration_max},
|
105
107
|
"steps": self.steps,
|
106
108
|
"bg_color": self.bg_color,
|
109
|
+
"padding_percent": self.padding_percent,
|
107
110
|
"fake_vid": self.fake_vid,
|
108
111
|
"quantize_method": self.quantize_method,
|
109
112
|
"scale_filter": self.scale_filter,
|
@@ -38,6 +38,7 @@
|
|
38
38
|
"min": 0,
|
39
39
|
"max": 10000
|
40
40
|
},
|
41
|
+
"padding_percent": 0,
|
41
42
|
"bg_color": "",
|
42
43
|
"steps": 16,
|
43
44
|
"fake_vid": false,
|
@@ -84,6 +85,7 @@
|
|
84
85
|
"min": 0,
|
85
86
|
"max": 3000
|
86
87
|
},
|
88
|
+
"padding_percent": 0,
|
87
89
|
"bg_color": "",
|
88
90
|
"steps": 16,
|
89
91
|
"fake_vid": false,
|
@@ -130,6 +132,7 @@
|
|
130
132
|
"min": 0,
|
131
133
|
"max": 3000
|
132
134
|
},
|
135
|
+
"padding_percent": 0,
|
133
136
|
"bg_color": "",
|
134
137
|
"steps": 16,
|
135
138
|
"fake_vid": false,
|
@@ -176,6 +179,7 @@
|
|
176
179
|
"min": 0,
|
177
180
|
"max": 3000
|
178
181
|
},
|
182
|
+
"padding_percent": 0,
|
179
183
|
"bg_color": "",
|
180
184
|
"steps": 16,
|
181
185
|
"fake_vid": false,
|
@@ -222,6 +226,7 @@
|
|
222
226
|
"min": 8,
|
223
227
|
"max": 10000
|
224
228
|
},
|
229
|
+
"padding_percent": 0,
|
225
230
|
"bg_color": "",
|
226
231
|
"steps": 16,
|
227
232
|
"fake_vid": true,
|
@@ -268,6 +273,7 @@
|
|
268
273
|
"min": 83,
|
269
274
|
"max": 4000
|
270
275
|
},
|
276
|
+
"padding_percent": 0,
|
271
277
|
"bg_color": "",
|
272
278
|
"steps": 16,
|
273
279
|
"fake_vid": false,
|
@@ -314,6 +320,7 @@
|
|
314
320
|
"min": 0,
|
315
321
|
"max": 5000
|
316
322
|
},
|
323
|
+
"padding_percent": 0,
|
317
324
|
"bg_color": "",
|
318
325
|
"steps": 16,
|
319
326
|
"fake_vid": false,
|
@@ -360,6 +367,7 @@
|
|
360
367
|
"min": 0,
|
361
368
|
"max": 2000
|
362
369
|
},
|
370
|
+
"padding_percent": 0,
|
363
371
|
"bg_color": "",
|
364
372
|
"steps": 16,
|
365
373
|
"fake_vid": false,
|
@@ -406,6 +414,7 @@
|
|
406
414
|
"min": 0,
|
407
415
|
"max": 2000
|
408
416
|
},
|
417
|
+
"padding_percent": 0,
|
409
418
|
"bg_color": "",
|
410
419
|
"steps": 16,
|
411
420
|
"fake_vid": false,
|
@@ -452,6 +461,7 @@
|
|
452
461
|
"min": 0,
|
453
462
|
"max": 2000
|
454
463
|
},
|
464
|
+
"padding_percent": 0,
|
455
465
|
"bg_color": "",
|
456
466
|
"steps": 16,
|
457
467
|
"fake_vid": false,
|
@@ -498,6 +508,7 @@
|
|
498
508
|
"min": 0,
|
499
509
|
"max": 10000
|
500
510
|
},
|
511
|
+
"padding_percent": 0,
|
501
512
|
"bg_color": "",
|
502
513
|
"steps": 16,
|
503
514
|
"fake_vid": false,
|
@@ -39,6 +39,7 @@
|
|
39
39
|
"duration": "Change playback speed if outside of duration limit.\nDuration set in miliseconds.\n0 will disable limit.",
|
40
40
|
"duration_min": "Set minimum output duration in miliseconds.",
|
41
41
|
"duration_max": "Set maximum output duration in miliseconds.",
|
42
|
+
"padding_percent": "Set percentage of space used as padding.",
|
42
43
|
"bg_color": "Set custom background color.\nExample: 00ff00 for green.\nIf this is not set, background color would be auto set to black if image is bright, or white if image is dark.\nNote: The color should not be visible if output format supports transparency.",
|
43
44
|
"size": "Set maximum file size in bytes for video and image.",
|
44
45
|
"vid_size_max": "Set maximum file size limit for animated stickers.",
|
@@ -3,13 +3,12 @@ import copy
|
|
3
3
|
import shutil
|
4
4
|
import zipfile
|
5
5
|
from pathlib import Path
|
6
|
-
from
|
7
|
-
from typing import Any, List, Union
|
6
|
+
from typing import Any, List
|
8
7
|
|
9
8
|
from sticker_convert.converter import StickerConvert
|
10
9
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
11
10
|
from sticker_convert.uploaders.upload_base import UploadBase
|
12
|
-
from sticker_convert.utils.callback import
|
11
|
+
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
13
12
|
from sticker_convert.utils.files.cache_store import CacheStore
|
14
13
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
15
14
|
from sticker_convert.utils.files.sanitize_filename import sanitize_filename
|
@@ -150,7 +149,7 @@ class CompressWastickers(UploadBase):
|
|
150
149
|
opt_output: OutputOption,
|
151
150
|
opt_comp: CompOption,
|
152
151
|
opt_cred: CredOption,
|
153
|
-
cb:
|
152
|
+
cb: CallbackProtocol,
|
154
153
|
cb_return: CallbackReturn,
|
155
154
|
) -> List[str]:
|
156
155
|
exporter = CompressWastickers(opt_output, opt_comp, opt_cred, cb, cb_return)
|
@@ -1,9 +1,7 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
|
-
from queue import Queue
|
3
|
-
from typing import Union
|
4
2
|
|
5
3
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
6
|
-
from sticker_convert.utils.callback import
|
4
|
+
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
7
5
|
|
8
6
|
|
9
7
|
class UploadBase:
|
@@ -12,13 +10,9 @@ class UploadBase:
|
|
12
10
|
opt_output: OutputOption,
|
13
11
|
opt_comp: CompOption,
|
14
12
|
opt_cred: CredOption,
|
15
|
-
cb:
|
13
|
+
cb: CallbackProtocol,
|
16
14
|
cb_return: CallbackReturn,
|
17
15
|
) -> None:
|
18
|
-
if not cb:
|
19
|
-
cb = Callback(silent=True)
|
20
|
-
cb_return = CallbackReturn()
|
21
|
-
|
22
16
|
self.opt_output = opt_output
|
23
17
|
self.opt_comp = opt_comp
|
24
18
|
self.opt_cred = opt_cred
|
@@ -1,8 +1,7 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
import copy
|
3
3
|
from pathlib import Path
|
4
|
-
from
|
5
|
-
from typing import Any, Dict, List, Union
|
4
|
+
from typing import Any, Dict, List
|
6
5
|
|
7
6
|
import anyio
|
8
7
|
from signalstickers_client import StickersClient # type: ignore
|
@@ -12,7 +11,7 @@ from signalstickers_client.models import LocalStickerPack, Sticker # type: igno
|
|
12
11
|
from sticker_convert.converter import StickerConvert
|
13
12
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
14
13
|
from sticker_convert.uploaders.upload_base import UploadBase
|
15
|
-
from sticker_convert.utils.callback import
|
14
|
+
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
16
15
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
17
16
|
from sticker_convert.utils.media.codec_info import CodecInfo
|
18
17
|
from sticker_convert.utils.media.format_verify import FormatVerify
|
@@ -167,7 +166,7 @@ class UploadSignal(UploadBase):
|
|
167
166
|
opt_output: OutputOption,
|
168
167
|
opt_comp: CompOption,
|
169
168
|
opt_cred: CredOption,
|
170
|
-
cb:
|
169
|
+
cb: CallbackProtocol,
|
171
170
|
cb_return: CallbackReturn,
|
172
171
|
) -> List[str]:
|
173
172
|
exporter = UploadSignal(opt_output, opt_comp, opt_cred, cb, cb_return)
|
@@ -2,7 +2,6 @@
|
|
2
2
|
import copy
|
3
3
|
import re
|
4
4
|
from pathlib import Path
|
5
|
-
from queue import Queue
|
6
5
|
from typing import Any, Dict, List, Optional, Tuple, Union, cast
|
7
6
|
|
8
7
|
import anyio
|
@@ -13,7 +12,7 @@ from telegram.ext import AIORateLimiter, ApplicationBuilder
|
|
13
12
|
from sticker_convert.converter import StickerConvert
|
14
13
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
15
14
|
from sticker_convert.uploaders.upload_base import UploadBase
|
16
|
-
from sticker_convert.utils.callback import
|
15
|
+
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
17
16
|
from sticker_convert.utils.files.metadata_handler import MetadataHandler
|
18
17
|
from sticker_convert.utils.media.format_verify import FormatVerify
|
19
18
|
|
@@ -79,7 +78,7 @@ class UploadTelegram(UploadBase):
|
|
79
78
|
application = ( # type: ignore
|
80
79
|
ApplicationBuilder()
|
81
80
|
.token(self.opt_cred.telegram_token.strip())
|
82
|
-
.rate_limiter(AIORateLimiter())
|
81
|
+
.rate_limiter(AIORateLimiter(max_retries=3))
|
83
82
|
.connect_timeout(timeout)
|
84
83
|
.pool_timeout(timeout)
|
85
84
|
.read_timeout(timeout)
|
@@ -350,7 +349,7 @@ class UploadTelegram(UploadBase):
|
|
350
349
|
opt_output: OutputOption,
|
351
350
|
opt_comp: CompOption,
|
352
351
|
opt_cred: CredOption,
|
353
|
-
cb:
|
352
|
+
cb: CallbackProtocol,
|
354
353
|
cb_return: CallbackReturn,
|
355
354
|
) -> List[str]:
|
356
355
|
exporter = UploadTelegram(
|
@@ -6,14 +6,13 @@ import plistlib
|
|
6
6
|
import shutil
|
7
7
|
import zipfile
|
8
8
|
from pathlib import Path
|
9
|
-
from
|
10
|
-
from typing import Any, Dict, List, Union
|
9
|
+
from typing import Any, Dict, List
|
11
10
|
|
12
11
|
from sticker_convert.converter import StickerConvert
|
13
12
|
from sticker_convert.definitions import ROOT_DIR
|
14
13
|
from sticker_convert.job_option import CompOption, CredOption, OutputOption
|
15
14
|
from sticker_convert.uploaders.upload_base import UploadBase
|
16
|
-
from sticker_convert.utils.callback import
|
15
|
+
from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
|
17
16
|
from sticker_convert.utils.files.metadata_handler import XCODE_IMESSAGE_ICONSET, MetadataHandler
|
18
17
|
from sticker_convert.utils.files.sanitize_filename import sanitize_filename
|
19
18
|
from sticker_convert.utils.media.codec_info import CodecInfo
|
@@ -279,7 +278,7 @@ class XcodeImessage(UploadBase):
|
|
279
278
|
opt_output: OutputOption,
|
280
279
|
opt_comp: CompOption,
|
281
280
|
opt_cred: CredOption,
|
282
|
-
cb:
|
281
|
+
cb: CallbackProtocol,
|
283
282
|
cb_return: CallbackReturn,
|
284
283
|
) -> List[str]:
|
285
284
|
exporter = XcodeImessage(opt_output, opt_comp, opt_cred, cb, cb_return)
|
@@ -1,39 +1,57 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
|
-
from multiprocessing import Event,
|
3
|
-
from
|
2
|
+
from multiprocessing import Event, Manager
|
3
|
+
from multiprocessing.managers import ListProxy, SyncManager
|
4
|
+
from queue import Queue
|
5
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
|
4
6
|
|
5
7
|
from tqdm import tqdm
|
6
8
|
|
7
9
|
CbQueueTupleType = Tuple[
|
8
10
|
Optional[str], Optional[Tuple[Any, ...]], Optional[Dict[str, Any]]
|
9
11
|
]
|
10
|
-
CbQueueItemType = Union[
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
CbQueueItemType = Union[CbQueueTupleType, str, None]
|
13
|
+
WorkQueueItemType = Optional[Tuple[Callable[..., Any], Tuple[Any, ...]]]
|
14
|
+
ResponseItemType = Union[bool, str, None]
|
15
|
+
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
# mypy complains about this
|
18
|
+
ResultsListType = ListProxy[Any] # type: ignore
|
19
|
+
ResponseListType = ListProxy[ResponseItemType] # type: ignore
|
20
|
+
CbQueueType = Queue[CbQueueItemType] # type: ignore
|
21
|
+
WorkQueueType = Queue[WorkQueueItemType] # type: ignore
|
22
|
+
else:
|
23
|
+
ResultsListType = List[Any]
|
24
|
+
ResponseListType = List[ResponseItemType]
|
25
|
+
CbQueueType = Queue
|
26
|
+
WorkQueueType = Queue
|
15
27
|
|
16
28
|
|
17
29
|
class CallbackReturn:
|
18
|
-
def __init__(self) -> None:
|
30
|
+
def __init__(self, manager: Optional[SyncManager] = None) -> None:
|
19
31
|
self.response_event = Event()
|
20
|
-
|
32
|
+
if manager is None:
|
33
|
+
manager = Manager()
|
34
|
+
self.response_queue: ResponseListType = manager.list()
|
21
35
|
|
22
|
-
def set_response(self, response:
|
23
|
-
self.response_queue.
|
36
|
+
def set_response(self, response: ResponseItemType) -> None:
|
37
|
+
self.response_queue.append(response)
|
24
38
|
self.response_event.set()
|
25
39
|
|
26
|
-
def get_response(self) ->
|
40
|
+
def get_response(self) -> ResponseItemType:
|
27
41
|
self.response_event.wait()
|
28
42
|
|
29
|
-
response = self.response_queue.
|
43
|
+
response = self.response_queue.pop()
|
30
44
|
|
31
45
|
self.response_event.clear()
|
32
46
|
|
33
47
|
return response
|
34
48
|
|
35
49
|
|
36
|
-
class
|
50
|
+
class CallbackProtocol(Protocol):
|
51
|
+
def put(self, i: Union[CbQueueItemType, str]) -> Any: ...
|
52
|
+
|
53
|
+
|
54
|
+
class Callback(CallbackProtocol):
|
37
55
|
def __init__(
|
38
56
|
self,
|
39
57
|
msg: Optional[Callable[..., None]] = None,
|
@@ -155,13 +173,7 @@ class Callback:
|
|
155
173
|
|
156
174
|
return response
|
157
175
|
|
158
|
-
def put(
|
159
|
-
self,
|
160
|
-
i: Union[
|
161
|
-
CbQueueItemType,
|
162
|
-
str,
|
163
|
-
],
|
164
|
-
) -> Union[str, bool, None]:
|
176
|
+
def put(self, i: Union[CbQueueItemType, str]) -> Union[str, bool, None]:
|
165
177
|
if isinstance(i, tuple):
|
166
178
|
action = i[0]
|
167
179
|
if len(i) >= 2:
|
@@ -258,11 +258,7 @@ class CodecInfo:
|
|
258
258
|
fps = frames_apparent / total_duration * 1000
|
259
259
|
return fps, frames, total_duration
|
260
260
|
|
261
|
-
return
|
262
|
-
0.0,
|
263
|
-
1,
|
264
|
-
0,
|
265
|
-
)
|
261
|
+
return 0.0, 1, 0
|
266
262
|
|
267
263
|
@staticmethod
|
268
264
|
def _get_file_fps_frames_duration_webp(
|
@@ -294,8 +290,8 @@ class CodecInfo:
|
|
294
290
|
total_duration += frame_duration
|
295
291
|
frames += 1
|
296
292
|
|
297
|
-
if frames
|
298
|
-
return 0.0,
|
293
|
+
if frames <= 1:
|
294
|
+
return 0.0, 1, 0
|
299
295
|
|
300
296
|
if len(durations) == 1:
|
301
297
|
fps = frames / total_duration * 1000
|
sticker_convert/version.py
CHANGED