sticker-convert 2.1.6__py3-none-any.whl → 2.1.7__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 (57) hide show
  1. sticker_convert/__init__.py +1 -1
  2. sticker_convert/__main__.py +7 -4
  3. sticker_convert/cli.py +39 -31
  4. sticker_convert/converter.py +432 -0
  5. sticker_convert/downloaders/download_base.py +40 -16
  6. sticker_convert/downloaders/download_kakao.py +103 -136
  7. sticker_convert/downloaders/download_line.py +16 -6
  8. sticker_convert/downloaders/download_signal.py +48 -32
  9. sticker_convert/downloaders/download_telegram.py +71 -26
  10. sticker_convert/gui.py +78 -129
  11. sticker_convert/{gui_frames → gui_components/frames}/comp_frame.py +2 -3
  12. sticker_convert/{gui_frames → gui_components/frames}/config_frame.py +3 -4
  13. sticker_convert/{gui_frames → gui_components/frames}/control_frame.py +2 -2
  14. sticker_convert/{gui_frames → gui_components/frames}/cred_frame.py +4 -4
  15. sticker_convert/{gui_frames → gui_components/frames}/input_frame.py +4 -4
  16. sticker_convert/{gui_frames → gui_components/frames}/output_frame.py +3 -3
  17. sticker_convert/{gui_frames → gui_components/frames}/progress_frame.py +1 -1
  18. sticker_convert/{utils → gui_components}/gui_utils.py +38 -21
  19. sticker_convert/{gui_windows → gui_components/windows}/advanced_compression_window.py +3 -2
  20. sticker_convert/{gui_windows → gui_components/windows}/base_window.py +3 -2
  21. sticker_convert/{gui_windows → gui_components/windows}/kakao_get_auth_window.py +3 -3
  22. sticker_convert/{gui_windows → gui_components/windows}/line_get_auth_window.py +2 -2
  23. sticker_convert/{gui_windows → gui_components/windows}/signal_get_auth_window.py +2 -2
  24. sticker_convert/{flow.py → job.py} +91 -102
  25. sticker_convert/job_option.py +301 -0
  26. sticker_convert/resources/compression.json +1 -1
  27. sticker_convert/uploaders/compress_wastickers.py +95 -74
  28. sticker_convert/uploaders/upload_base.py +16 -4
  29. sticker_convert/uploaders/upload_signal.py +100 -62
  30. sticker_convert/uploaders/upload_telegram.py +168 -128
  31. sticker_convert/uploaders/xcode_imessage.py +202 -132
  32. sticker_convert/{auth → utils/auth}/get_kakao_auth.py +7 -5
  33. sticker_convert/{auth → utils/auth}/get_line_auth.py +3 -3
  34. sticker_convert/{auth → utils/auth}/get_signal_auth.py +1 -1
  35. sticker_convert/utils/fake_cb_msg.py +5 -2
  36. sticker_convert/utils/{cache_store.py → files/cache_store.py} +7 -3
  37. sticker_convert/utils/files/dir_utils.py +64 -0
  38. sticker_convert/utils/{json_manager.py → files/json_manager.py} +5 -4
  39. sticker_convert/utils/files/metadata_handler.py +226 -0
  40. sticker_convert/utils/files/run_bin.py +58 -0
  41. sticker_convert/utils/{apple_png_normalize.py → media/apple_png_normalize.py} +23 -20
  42. sticker_convert/utils/{codec_info.py → media/codec_info.py} +41 -35
  43. sticker_convert/utils/media/decrypt_kakao.py +68 -0
  44. sticker_convert/utils/media/format_verify.py +184 -0
  45. sticker_convert/utils/url_detect.py +16 -14
  46. {sticker_convert-2.1.6.dist-info → sticker_convert-2.1.7.dist-info}/METADATA +8 -9
  47. {sticker_convert-2.1.6.dist-info → sticker_convert-2.1.7.dist-info}/RECORD +52 -50
  48. {sticker_convert-2.1.6.dist-info → sticker_convert-2.1.7.dist-info}/WHEEL +1 -1
  49. sticker_convert/utils/converter.py +0 -407
  50. sticker_convert/utils/curr_dir.py +0 -70
  51. sticker_convert/utils/format_verify.py +0 -188
  52. sticker_convert/utils/metadata_handler.py +0 -190
  53. sticker_convert/utils/run_bin.py +0 -46
  54. /sticker_convert/{gui_frames → gui_components/frames}/right_clicker.py +0 -0
  55. {sticker_convert-2.1.6.dist-info → sticker_convert-2.1.7.dist-info}/LICENSE +0 -0
  56. {sticker_convert-2.1.6.dist-info → sticker_convert-2.1.7.dist-info}/entry_points.txt +0 -0
  57. {sticker_convert-2.1.6.dist-info → sticker_convert-2.1.7.dist-info}/top_level.txt +0 -0
@@ -4,57 +4,53 @@ import copy
4
4
  from typing import Optional
5
5
 
6
6
  import anyio
7
- from signalstickers_client import StickersClient # type: ignore
8
- from signalstickers_client.models import LocalStickerPack, Sticker # type: ignore
9
- from mergedeep import merge # type: ignore
7
+ from signalstickers_client import StickersClient # type: ignore
8
+ from signalstickers_client.models import LocalStickerPack, Sticker # type: ignore
9
+
10
+ from .upload_base import UploadBase # type: ignore
11
+ from ..utils.files.metadata_handler import MetadataHandler # type: ignore
12
+ from ..converter import StickerConvert # type: ignore
13
+ from ..utils.media.format_verify import FormatVerify # type: ignore
14
+ from ..utils.media.codec_info import CodecInfo # type: ignore
15
+ from ..job_option import CompOption, OutputOption, CredOption # type: ignore
10
16
 
11
- from .upload_base import UploadBase # type: ignore
12
- from ..utils.metadata_handler import MetadataHandler # type: ignore
13
- from ..utils.converter import StickerConvert # type: ignore
14
- from ..utils.format_verify import FormatVerify # type: ignore
15
- from ..utils.codec_info import CodecInfo # type: ignore
16
17
 
17
18
  class UploadSignal(UploadBase):
18
19
  def __init__(self, *args, **kwargs):
19
20
  super(UploadSignal, self).__init__(*args, **kwargs)
20
-
21
- base_spec = {
22
- "size_max": {
23
- "img": 300000,
24
- "vid": 300000
25
- },
26
- 'res': {
27
- 'w': {
28
- 'max': 512
29
- },
30
- 'h': {
31
- 'max': 512
32
- }
33
- },
34
- 'duration': {
35
- 'max': 3000
36
- },
37
- 'square': True
38
- }
21
+
22
+ base_spec = CompOption({
23
+ "size_max": {"img": 300000, "vid": 300000},
24
+ "res": {"max": 512},
25
+ "duration": {"max": 3000},
26
+ "square": True,
27
+ })
39
28
 
40
29
  self.png_spec = copy.deepcopy(base_spec)
30
+ self.png_spec.format_vid = '.apng'
41
31
 
42
32
  self.webp_spec = copy.deepcopy(base_spec)
43
- self.webp_spec['animated'] = False
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(base_spec)
44
38
 
45
- self.opt_comp_merged = merge({}, self.opt_comp, base_spec)
46
-
47
39
  @staticmethod
48
40
  async def upload_pack(pack: LocalStickerPack, uuid: str, password: str):
49
41
  async with StickersClient(uuid, password) as client:
50
42
  pack_id, pack_key = await client.upload_pack(pack)
51
43
 
52
- result = f"https://signal.art/addstickers/#pack_id={pack_id}&pack_key={pack_key}"
44
+ result = (
45
+ f"https://signal.art/addstickers/#pack_id={pack_id}&pack_key={pack_key}"
46
+ )
53
47
  return result
54
-
55
- def add_stickers_to_pack(self, pack: LocalStickerPack, stickers: list[str], emoji_dict: dict):
48
+
49
+ def add_stickers_to_pack(
50
+ self, pack: LocalStickerPack, stickers: list[str], emoji_dict: dict
51
+ ):
56
52
  for src in stickers:
57
- self.cb_msg(f'Verifying {src} for uploading to signal')
53
+ self.cb_msg(f"Verifying {src} for uploading to signal")
58
54
 
59
55
  src_full_name = os.path.split(src)[-1]
60
56
  src_name = os.path.splitext(src_full_name)[0]
@@ -65,21 +61,25 @@ class UploadSignal(UploadBase):
65
61
 
66
62
  emoji = emoji_dict.get(src_name, None)
67
63
  if not emoji:
68
- self.cb_msg(f'Warning: Cannot find emoji for file {src_full_name}, skip uploading this file...')
64
+ self.cb_msg(
65
+ f"Warning: Cannot find emoji for file {src_full_name}, skip uploading this file..."
66
+ )
69
67
  continue
70
68
  sticker.emoji = emoji[:1]
71
69
 
72
- if ext == '.webp':
70
+ if ext == ".webp":
73
71
  spec_choice = self.webp_spec
74
72
  else:
75
73
  spec_choice = self.png_spec
76
-
74
+
77
75
  if not FormatVerify.check_file(src, spec=spec_choice):
78
76
  if self.fake_vid or CodecInfo.is_anim(src):
79
- dst = 'bytes.apng'
77
+ dst = "bytes.apng"
80
78
  else:
81
- dst = 'bytes.png'
82
- _, _, sticker.image_data, _ = StickerConvert(src, dst, self.opt_comp_merged, self.cb_msg).convert()
79
+ dst = "bytes.png"
80
+ _, _, sticker.image_data, _ = StickerConvert(
81
+ src, dst, self.opt_comp_merged, self.cb_msg
82
+ ).convert()
83
83
  else:
84
84
  with open(src, "rb") as f:
85
85
  sticker.image_data = f.read()
@@ -89,45 +89,83 @@ class UploadSignal(UploadBase):
89
89
  def upload_stickers_signal(self) -> list[str]:
90
90
  urls = []
91
91
 
92
- if not self.opt_cred.get('signal', {}).get('uuid'):
93
- self.cb_msg('uuid required for uploading to Signal')
92
+ if not self.opt_cred.signal_uuid:
93
+ self.cb_msg("uuid required for uploading to Signal")
94
94
  return urls
95
- if not self.opt_cred.get('signal', {}).get('password'):
96
- self.cb_msg('password required for uploading to Signal')
95
+ if not self.opt_cred.signal_password:
96
+ self.cb_msg("password required for uploading to Signal")
97
97
  return urls
98
-
99
- title, author, emoji_dict = MetadataHandler.get_metadata(self.in_dir, title=self.opt_output.get('title'), author=self.opt_output.get('author'))
98
+
99
+ title, author, emoji_dict = MetadataHandler.get_metadata(
100
+ self.in_dir,
101
+ title=self.opt_output.title,
102
+ author=self.opt_output.author,
103
+ )
100
104
  if title == None:
101
- raise TypeError(f'title cannot be {title}')
105
+ raise TypeError(f"title cannot be {title}")
102
106
  if author == None:
103
- raise TypeError(f'author cannot be {author}')
107
+ raise TypeError(f"author cannot be {author}")
104
108
  if emoji_dict == None:
105
- msg_block = 'emoji.txt is required for uploading signal stickers\n'
106
- msg_block += f'emoji.txt generated for you in {self.in_dir}\n'
107
- msg_block += f'Default emoji is set to {self.opt_comp.get("default_emoji")}.\n'
108
- msg_block += 'Please edit emoji.txt now, then continue'
109
- MetadataHandler.generate_emoji_file(dir=self.in_dir, default_emoji=self.opt_comp.get("default_emoji"))
109
+ msg_block = "emoji.txt is required for uploading signal stickers\n"
110
+ msg_block += f"emoji.txt generated for you in {self.in_dir}\n"
111
+ msg_block += (
112
+ f'Default emoji is set to {self.opt_comp.default_emoji}.\n'
113
+ )
114
+ msg_block += "Please edit emoji.txt now, then continue"
115
+ MetadataHandler.generate_emoji_file(
116
+ dir=self.in_dir, default_emoji=self.opt_comp.default_emoji
117
+ )
110
118
 
111
119
  self.cb_msg_block(msg_block)
112
120
 
113
- title, author, emoji_dict = MetadataHandler.get_metadata(self.in_dir, title=self.opt_output.get('title'), author=self.opt_output.get('author'))
114
-
115
- packs = MetadataHandler.split_sticker_packs(self.in_dir, title=title, file_per_pack=200, separate_image_anim=False)
121
+ title, author, emoji_dict = MetadataHandler.get_metadata(
122
+ self.in_dir,
123
+ title=self.opt_output.title,
124
+ author=self.opt_output.author,
125
+ )
126
+
127
+ packs = MetadataHandler.split_sticker_packs(
128
+ self.in_dir, title=title, file_per_pack=200, separate_image_anim=False
129
+ )
116
130
  for pack_title, stickers in packs.items():
117
- self.cb_msg(f'Uploading pack {pack_title}')
118
131
  pack = LocalStickerPack()
119
132
  pack.title = pack_title
120
133
  pack.author = author
121
134
 
122
135
  self.add_stickers_to_pack(pack, stickers, emoji_dict)
123
- result = anyio.run(UploadSignal.upload_pack, pack, self.opt_cred.get('signal', {}).get('uuid'), self.opt_cred.get('signal', {}).get('password'))
136
+ self.cb_msg(f"Uploading pack {pack_title}")
137
+ result = anyio.run(
138
+ UploadSignal.upload_pack,
139
+ pack,
140
+ self.opt_cred.signal_uuid,
141
+ self.opt_cred.signal_password,
142
+ )
124
143
 
125
144
  self.cb_msg(result)
126
145
  urls.append(result)
127
-
146
+
128
147
  return urls
129
148
 
130
149
  @staticmethod
131
- def start(opt_output: dict, opt_comp: dict, opt_cred: dict, cb_msg=print, cb_msg_block=input, cb_ask_bool=input, cb_bar=None, out_dir: Optional[str] = None, **kwargs) -> list[str]:
132
- exporter = UploadSignal(opt_output, opt_comp, opt_cred, cb_msg, cb_msg_block, cb_ask_bool, cb_bar, out_dir)
133
- return exporter.upload_stickers_signal()
150
+ def start(
151
+ opt_output: OutputOption,
152
+ opt_comp: CompOption,
153
+ opt_cred: CredOption,
154
+ cb_msg=print,
155
+ cb_msg_block=input,
156
+ cb_ask_bool=input,
157
+ cb_bar=None,
158
+ out_dir: Optional[str] = None,
159
+ **kwargs,
160
+ ) -> list[str]:
161
+ exporter = UploadSignal(
162
+ opt_output,
163
+ opt_comp,
164
+ opt_cred,
165
+ cb_msg,
166
+ cb_msg_block,
167
+ cb_ask_bool,
168
+ cb_bar,
169
+ out_dir,
170
+ )
171
+ return exporter.upload_stickers_signal()
@@ -7,123 +7,112 @@ from typing import Optional
7
7
  import anyio
8
8
  from telegram import Bot, InputSticker
9
9
  from telegram.error import TelegramError
10
- from mergedeep import merge # type: ignore
11
10
 
12
- from .upload_base import UploadBase # type: ignore
13
- from ..utils.converter import StickerConvert # type: ignore
14
- from ..utils.metadata_handler import MetadataHandler # type: ignore
15
- from ..utils.format_verify import FormatVerify # type: ignore
11
+ from .upload_base import UploadBase # type: ignore
12
+ from ..converter import StickerConvert # type: ignore
13
+ from ..utils.files.metadata_handler import MetadataHandler # type: ignore
14
+ from ..utils.media.format_verify import FormatVerify # type: ignore
15
+ from ..job_option import CompOption, OutputOption, CredOption # type: ignore
16
+
16
17
 
17
18
  class UploadTelegram(UploadBase):
18
19
  def __init__(self, *args, **kwargs):
19
20
  super(UploadTelegram, self).__init__(*args, **kwargs)
20
-
21
- base_spec = {
22
- "size_max": {
23
- "img": 512000,
24
- "vid": 256000
25
- },
26
- 'res': {
27
- 'w': {
28
- 'min': 512,
29
- 'max': 512
30
- },
31
- 'h': {
32
- 'min': 512,
33
- 'max': 512
34
- }
35
- },
36
- 'square': True,
37
- 'duration': {
38
- 'max': 3000
39
- },
40
- 'fps': {}
41
- }
21
+
22
+ base_spec = CompOption({
23
+ "size_max": {"img": 512000, "vid": 256000},
24
+ "res": 512,
25
+ "square": True,
26
+ "duration": {"max": 3000}
27
+ })
42
28
 
43
29
  self.png_spec = copy.deepcopy(base_spec)
44
- self.png_spec['format'] = '.png'
45
- self.png_spec['animated'] = False
30
+ self.png_spec.format = ".png"
31
+ self.png_spec.animated = False
46
32
 
47
33
  self.tgs_spec = copy.deepcopy(base_spec)
48
- self.tgs_spec['format'] = '.tgs'
49
- self.tgs_spec['fps']['min'] = 60
50
- self.tgs_spec['fps']['max'] = 60
51
- self.tgs_spec['size_max']['img'] = 64000
52
- self.tgs_spec['size_max']['vid'] = 64000
34
+ self.tgs_spec.format = ".tgs"
35
+ self.tgs_spec.fps_min = 60
36
+ self.tgs_spec.fps_max = 60
37
+ self.tgs_spec.size_max_img = 64000
38
+ self.tgs_spec.size_max_vid = 64000
53
39
 
54
40
  self.webm_spec = copy.deepcopy(base_spec)
55
- self.webm_spec['format'] = '.webm'
56
- self.webm_spec['fps']['max'] = 30
57
- self.webm_spec['animated'] = None if self.fake_vid else True
58
-
59
- self.opt_comp_merged = merge({}, self.opt_comp, base_spec)
60
-
61
- base_cover_spec = {
62
- "size_max": {
63
- "img": 128000,
64
- "vid": 32000
65
- },
66
- 'res': {
67
- 'w': {
68
- 'min': 100,
69
- 'max': 100
70
- },
71
- 'h': {
72
- 'min': 100,
73
- 'max': 100
74
- }
75
- },
76
- 'square': True,
77
- 'duration': {
78
- 'max': 3000
79
- },
80
- 'fps': {}
81
- }
41
+ self.webm_spec.format = ".webm"
42
+ self.webm_spec.fps_max = 30
43
+ self.webm_spec.animated = None if self.fake_vid else True
44
+
45
+ self.opt_comp_merged = copy.deepcopy(self.opt_comp)
46
+ self.opt_comp_merged.merge(base_spec)
47
+
48
+ base_cover_spec = CompOption({
49
+ "size_max": {"img": 128000, "vid": 32000},
50
+ "res": 100,
51
+ "square": True,
52
+ "duration": {"max": 3000}
53
+ })
82
54
 
83
55
  self.png_cover_spec = copy.deepcopy(base_cover_spec)
84
- self.png_cover_spec['format'] = '.png'
85
- self.png_cover_spec['animated'] = False
56
+ self.png_cover_spec.format = ".png"
57
+ self.png_cover_spec.animated = False
86
58
 
87
59
  self.tgs_cover_spec = copy.deepcopy(base_cover_spec)
88
- self.tgs_cover_spec['format'] = '.tgs'
89
- self.tgs_cover_spec['fps']['min'] = 60
90
- self.tgs_cover_spec['fps']['max'] = 60
60
+ self.tgs_cover_spec.format = ".tgs"
61
+ self.tgs_cover_spec.fps_min = 60
62
+ self.tgs_cover_spec.fps_max = 60
91
63
 
92
64
  self.webm_cover_spec = copy.deepcopy(base_cover_spec)
93
- self.webm_cover_spec['format'] = '.webm'
94
- self.webm_cover_spec['fps']['max'] = 30
95
- self.webm_cover_spec['animated'] = True
65
+ self.webm_cover_spec.format = ".webm"
66
+ self.webm_cover_spec.fps_max = 30
67
+ self.webm_cover_spec.animated = True
68
+
69
+ self.opt_comp_cover_merged = copy.deepcopy(self.opt_comp)
70
+ self.opt_comp_cover_merged.merge(base_spec)
96
71
 
97
- self.opt_comp_cover_merged = merge({}, self.opt_comp, base_cover_spec)
98
-
99
- async def upload_pack(self, pack_title: str, stickers: list[str], emoji_dict: dict[str, str]) -> str:
100
- bot = Bot(self.opt_cred['telegram']['token'])
72
+ async def upload_pack(
73
+ self, pack_title: str, stickers: list[str], emoji_dict: dict[str, str]
74
+ ) -> str:
75
+ bot = Bot(self.opt_cred.telegram_token)
101
76
 
102
77
  async with bot:
103
- pack_short_name = pack_title.replace(' ', '_') + '_by_' + bot.name.replace('@', '')
104
- pack_short_name = re.sub('[^0-9a-zA-Z]+', '_', pack_short_name) # name used in url, only alphanum and underscore only
105
-
78
+ pack_short_name = (
79
+ pack_title.replace(" ", "_") + "_by_" + bot.name.replace("@", "")
80
+ )
81
+ pack_short_name = re.sub(
82
+ "[^0-9a-zA-Z]+", "_", pack_short_name
83
+ ) # name used in url, only alphanum and underscore only
84
+
106
85
  try:
107
- sticker_set = await bot.get_sticker_set(pack_short_name, read_timeout=30, write_timeout=30, connect_timeout=30, pool_timeout=30)
86
+ sticker_set = await bot.get_sticker_set(
87
+ pack_short_name,
88
+ read_timeout=30,
89
+ write_timeout=30,
90
+ connect_timeout=30,
91
+ pool_timeout=30,
92
+ )
108
93
  await bot.get_sticker_set(pack_short_name)
109
94
  pack_exists = True
110
95
  except TelegramError:
111
96
  pack_exists = False
112
97
 
113
98
  if pack_exists == True:
114
- response = self.cb_ask_bool(f'Warning: Pack {pack_short_name} already exists.\nDelete all stickers in pack?')
99
+ response = self.cb_ask_bool(
100
+ f"Warning: Pack {pack_short_name} already exists.\nDelete all stickers in pack?"
101
+ )
115
102
  if response == True:
116
- self.cb_msg(f'Deleting all stickers from pack {pack_short_name}')
103
+ self.cb_msg(f"Deleting all stickers from pack {pack_short_name}")
117
104
  try:
118
105
  for i in sticker_set.stickers:
119
106
  await bot.delete_sticker_from_set(i.file_id)
120
107
  except TelegramError as e:
121
- self.cb_msg(f'Cannot delete sticker {i.file_id} from {pack_short_name} due to {e}')
108
+ self.cb_msg(
109
+ f"Cannot delete sticker {i.file_id} from {pack_short_name} due to {e}"
110
+ )
122
111
  else:
123
- self.cb_msg(f'Not deleting existing pack {pack_short_name}')
112
+ self.cb_msg(f"Not deleting existing pack {pack_short_name}")
124
113
 
125
114
  for src in stickers:
126
- self.cb_msg(f'Verifying {src} for uploading to telegram')
115
+ self.cb_msg(f"Verifying {src} for uploading to telegram")
127
116
 
128
117
  src_full_name = os.path.split(src)[-1]
129
118
  src_name = os.path.splitext(src_full_name)[0]
@@ -132,109 +121,160 @@ class UploadTelegram(UploadBase):
132
121
  emoji = emoji_dict.get(src_name, None)
133
122
  if emoji:
134
123
  if len(emoji) > 20:
135
- self.cb_msg(f'Warning: {len(emoji)} emoji for file {src_full_name}, exceeding limit of 20, keep first 20 only...')
124
+ self.cb_msg(
125
+ f"Warning: {len(emoji)} emoji for file {src_full_name}, exceeding limit of 20, keep first 20 only..."
126
+ )
136
127
  emoji_list = [*emoji][:20]
137
128
  else:
138
- self.cb_msg(f'Warning: Cannot find emoji for file {src_full_name}, skip uploading this file...')
129
+ self.cb_msg(
130
+ f"Warning: Cannot find emoji for file {src_full_name}, skip uploading this file..."
131
+ )
139
132
  continue
140
133
 
141
- if ext == '.tgs':
134
+ if ext == ".tgs":
142
135
  spec_choice = self.tgs_spec
143
136
  cover_spec_choice = self.tgs_cover_spec
144
- sticker_format = 'animated'
145
- elif ext == '.webm':
137
+ sticker_format = "animated"
138
+ elif ext == ".webm":
146
139
  spec_choice = self.webm_spec
147
140
  cover_spec_choice = self.webm_cover_spec
148
- sticker_format = 'video'
141
+ sticker_format = "video"
149
142
  else:
150
- ext = '.png'
143
+ ext = ".png"
151
144
  spec_choice = self.png_spec
152
145
  cover_spec_choice = self.png_cover_spec
153
- sticker_format = 'static'
146
+ sticker_format = "static"
154
147
 
155
148
  if FormatVerify.check_file(src, spec=spec_choice):
156
- with open(src, 'rb') as f:
149
+ with open(src, "rb") as f:
157
150
  sticker_bytes = f.read()
158
151
  else:
159
- _, _, sticker_bytes, _ = StickerConvert(src, f'bytes{ext}', self.opt_comp_merged, self.cb_msg).convert()
160
-
161
- sticker = InputSticker(
162
- sticker=sticker_bytes,
163
- emoji_list=emoji_list
164
- )
152
+ _, _, sticker_bytes, _ = StickerConvert(
153
+ src, f"bytes{ext}", self.opt_comp_merged, self.cb_msg
154
+ ).convert()
155
+
156
+ sticker = InputSticker(sticker=sticker_bytes, emoji_list=emoji_list)
165
157
 
166
158
  try:
167
159
  if pack_exists == False:
168
160
  await bot.create_new_sticker_set(
169
- user_id=self.opt_cred['telegram']['userid'],
161
+ user_id=self.opt_cred.telegram_userid,
170
162
  name=pack_short_name,
171
163
  title=pack_title,
172
164
  stickers=[sticker],
173
- sticker_format=sticker_format)
165
+ sticker_format=sticker_format,
166
+ )
174
167
  pack_exists = True
175
168
  else:
176
169
  await bot.add_sticker_to_set(
177
- user_id=self.opt_cred['telegram']['userid'],
170
+ user_id=self.opt_cred.telegram_userid,
178
171
  name=pack_short_name,
179
- sticker=sticker)
172
+ sticker=sticker,
173
+ )
180
174
  except TelegramError as e:
181
- self.cb_msg(f'Cannot upload sticker {src} in {pack_short_name} due to {e}')
175
+ self.cb_msg(
176
+ f"Cannot upload sticker {src} in {pack_short_name} due to {e}"
177
+ )
182
178
  continue
183
179
 
184
- self.cb_msg(f'Uploaded {src}')
185
-
180
+ self.cb_msg(f"Uploaded {src}")
181
+
186
182
  cover_path = MetadataHandler.get_cover(self.in_dir)
187
183
  if cover_path:
188
184
  if FormatVerify.check_file(cover_path, spec=cover_spec_choice):
189
- with open(cover_path, 'rb') as f:
185
+ with open(cover_path, "rb") as f:
190
186
  thumbnail_bytes = f.read()
191
187
  else:
192
- _, _, thumbnail_bytes, _ = StickerConvert(cover_path, f'bytes{ext}', self.opt_comp_cover_merged, self.cb_msg).convert()
188
+ _, _, thumbnail_bytes, _ = StickerConvert(
189
+ cover_path,
190
+ f"bytes{ext}",
191
+ self.opt_comp_cover_merged,
192
+ self.cb_msg,
193
+ ).convert()
193
194
 
194
195
  try:
195
196
  await bot.set_sticker_set_thumbnail(
196
197
  name=pack_short_name,
197
- user_id=self.opt_cred['telegram']['userid'],
198
- thumbnail=thumbnail_bytes
198
+ user_id=self.opt_cred.telegram_userid,
199
+ thumbnail=thumbnail_bytes,
199
200
  )
200
201
  except TelegramError as e:
201
- self.cb_msg(f'Cannot upload cover (thumbnail) for {pack_short_name} due to {e}')
202
-
203
- result = f'https://t.me/addstickers/{pack_short_name}'
202
+ self.cb_msg(
203
+ f"Cannot upload cover (thumbnail) for {pack_short_name} due to {e}"
204
+ )
205
+
206
+ result = f"https://t.me/addstickers/{pack_short_name}"
204
207
  return result
205
208
 
206
209
  def upload_stickers_telegram(self) -> list[str]:
207
210
  urls = []
208
211
 
209
- if not self.opt_cred.get('telegram', {}).get('token'):
210
- self.cb_msg('Token required for uploading to telegram')
212
+ if not self.opt_cred.telegram_token:
213
+ self.cb_msg("Token required for uploading to telegram")
211
214
  return urls
212
-
213
- title, author, emoji_dict = MetadataHandler.get_metadata(self.in_dir, title=self.opt_output.get('title'), author=self.opt_output.get('author'))
215
+
216
+ title, author, emoji_dict = MetadataHandler.get_metadata(
217
+ self.in_dir,
218
+ title=self.opt_output.title,
219
+ author=self.opt_output.author,
220
+ )
214
221
  if title == None:
215
- raise TypeError('title cannot be', title)
222
+ raise TypeError("title cannot be", title)
216
223
  if emoji_dict == None:
217
- msg_block = 'emoji.txt is required for uploading signal stickers\n'
218
- msg_block += f'emoji.txt generated for you in {self.in_dir}\n'
219
- msg_block += f'Default emoji is set to {self.opt_comp.get("default_emoji")}.\n'
220
- msg_block += f'Please edit emoji.txt now, then continue'
221
- MetadataHandler.generate_emoji_file(dir=self.in_dir, default_emoji=self.opt_comp.get("default_emoji"))
224
+ msg_block = "emoji.txt is required for uploading signal stickers\n"
225
+ msg_block += f"emoji.txt generated for you in {self.in_dir}\n"
226
+ msg_block += (
227
+ f'Default emoji is set to {self.opt_comp.default_emoji}.\n'
228
+ )
229
+ msg_block += f"Please edit emoji.txt now, then continue"
230
+ MetadataHandler.generate_emoji_file(
231
+ dir=self.in_dir, default_emoji=self.opt_comp.default_emoji
232
+ )
222
233
 
223
234
  self.cb_msg_block(msg_block)
224
235
 
225
- title, author, emoji_dict = MetadataHandler.get_metadata(self.in_dir, title=self.opt_output.get('title'), author=self.opt_output.get('author'))
236
+ title, author, emoji_dict = MetadataHandler.get_metadata(
237
+ self.in_dir,
238
+ title=self.opt_output.title,
239
+ author=self.opt_output.author,
240
+ )
226
241
 
227
- packs = MetadataHandler.split_sticker_packs(self.in_dir, title=title, file_per_anim_pack=50, file_per_image_pack=120, separate_image_anim=not self.fake_vid)
242
+ packs = MetadataHandler.split_sticker_packs(
243
+ self.in_dir,
244
+ title=title,
245
+ file_per_anim_pack=50,
246
+ file_per_image_pack=120,
247
+ separate_image_anim=not self.fake_vid,
248
+ )
228
249
 
229
250
  for pack_title, stickers in packs.items():
230
- self.cb_msg(f'Uploading pack {pack_title}')
251
+ self.cb_msg(f"Uploading pack {pack_title}")
231
252
  result = anyio.run(self.upload_pack, pack_title, stickers, emoji_dict)
232
253
  self.cb_msg(result)
233
254
  urls.append(result)
234
255
 
235
256
  return urls
236
-
257
+
237
258
  @staticmethod
238
- def start(opt_output: dict, opt_comp: dict, opt_cred: dict, cb_msg=print, cb_msg_block=input, cb_ask_bool=input, cb_bar=None, out_dir: Optional[str] = None, **kwargs) -> list[str]:
239
- exporter = UploadTelegram(opt_output, opt_comp, opt_cred, cb_msg, cb_msg_block, cb_ask_bool, cb_bar, out_dir)
240
- return exporter.upload_stickers_telegram()
259
+ def start(
260
+ opt_output: OutputOption,
261
+ opt_comp: CompOption,
262
+ opt_cred: CredOption,
263
+ cb_msg=print,
264
+ cb_msg_block=input,
265
+ cb_ask_bool=input,
266
+ cb_bar=None,
267
+ out_dir: Optional[str] = None,
268
+ **kwargs,
269
+ ) -> list[str]:
270
+ exporter = UploadTelegram(
271
+ opt_output,
272
+ opt_comp,
273
+ opt_cred,
274
+ cb_msg,
275
+ cb_msg_block,
276
+ cb_ask_bool,
277
+ cb_bar,
278
+ out_dir,
279
+ )
280
+ return exporter.upload_stickers_telegram()