sticker-convert 2.1.5__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 +42 -32
  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 +30 -12
  8. sticker_convert/downloaders/download_signal.py +48 -32
  9. sticker_convert/downloaders/download_telegram.py +71 -26
  10. sticker_convert/gui.py +79 -130
  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 +6 -5
  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.5.dist-info → sticker_convert-2.1.7.dist-info}/METADATA +11 -11
  47. {sticker_convert-2.1.5.dist-info → sticker_convert-2.1.7.dist-info}/RECORD +52 -50
  48. {sticker_convert-2.1.5.dist-info → sticker_convert-2.1.7.dist-info}/WHEEL +1 -1
  49. sticker_convert/utils/converter.py +0 -399
  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.5.dist-info → sticker_convert-2.1.7.dist-info}/LICENSE +0 -0
  56. {sticker_convert-2.1.5.dist-info → sticker_convert-2.1.7.dist-info}/entry_points.txt +0 -0
  57. {sticker_convert-2.1.5.dist-info → sticker_convert-2.1.7.dist-info}/top_level.txt +0 -0
@@ -1,190 +0,0 @@
1
- #!/usr/bin/env python3
2
- import os
3
- import json
4
- from typing import Optional
5
-
6
- from .codec_info import CodecInfo # type: ignore
7
- from .json_manager import JsonManager # type: ignore
8
-
9
- class MetadataHandler:
10
- @staticmethod
11
- def get_stickers_present(dir: str) -> list[str]:
12
- from ..uploaders.xcode_imessage import XcodeImessageIconset # type: ignore
13
-
14
- stickers_present = sorted(os.listdir(dir))
15
- for i in stickers_present:
16
- if os.path.splitext(i)[0] == 'cover':
17
- stickers_present.remove(os.path.split(i)[1])
18
- for icon in XcodeImessageIconset().iconset:
19
- if icon in stickers_present:
20
- stickers_present.remove(icon)
21
- if '.DS_Store' in stickers_present:
22
- stickers_present.remove('.DS_Store')
23
- if '._.DS_Store' in stickers_present:
24
- stickers_present.remove('._.DS_Store')
25
- stickers_present = [i for i in stickers_present if os.path.isfile(os.path.join(dir, i)) and not i.endswith(('.txt', '.m4a'))]
26
-
27
- return stickers_present
28
-
29
- @staticmethod
30
- def get_cover(dir: str) -> Optional[str]:
31
- stickers_present = sorted(os.listdir(dir))
32
- for i in stickers_present:
33
- if os.path.splitext(i)[0] == 'cover':
34
- return os.path.join(dir, i)
35
-
36
- return None
37
-
38
- @staticmethod
39
- def get_metadata(dir: str, title: Optional[str] = None, author: Optional[str] = None, emoji_dict: Optional[dict[str, str]] = None) -> tuple[Optional[str], Optional[str], Optional[dict[str, str]]]:
40
- title_path = os.path.join(dir, 'title.txt')
41
- if not title and os.path.isfile(title_path):
42
- with open(title_path, encoding='utf-8') as f:
43
- title = f.read().strip()
44
-
45
- author_path = os.path.join(dir, 'author.txt')
46
- if not author and os.path.isfile(author_path):
47
- with open(author_path, encoding='utf-8') as f:
48
- author = f.read().strip()
49
-
50
- emoji_path = os.path.join(dir, 'emoji.txt')
51
- if not emoji_dict and os.path.isfile(emoji_path):
52
- with open(emoji_path , "r", encoding='utf-8') as f:
53
- emoji_dict = json.load(f)
54
-
55
- return title, author, emoji_dict
56
-
57
- @staticmethod
58
- def set_metadata(dir: str, title: Optional[str] = None, author: Optional[str] = None, emoji_dict: Optional[dict[str, str]] = None):
59
- title_path = os.path.join(dir, 'title.txt')
60
- if title != None:
61
- with open(title_path, 'w+', encoding='utf-8') as f:
62
- f.write(title) # type: ignore[arg-type]
63
-
64
- author_path = os.path.join(dir, 'author.txt')
65
- if author != None:
66
- with open(author_path, 'w+', encoding='utf-8') as f:
67
- f.write(author) # type: ignore[arg-type]
68
-
69
- emoji_path = os.path.join(dir, 'emoji.txt')
70
- if emoji_dict != None:
71
- with open(emoji_path, 'w+', encoding='utf-8') as f:
72
- json.dump(emoji_dict, f, indent=4, ensure_ascii=False)
73
-
74
- @staticmethod
75
- def check_metadata_provided(input_dir: str, input_option: str, metadata: str) -> bool:
76
- # Check if metadata provided via .txt file (if from local) or will be provided by input source (if not from local)
77
- # Does not check if metadata provided via user input in GUI or flag options
78
- # metadata = 'title' or 'author'
79
- input_presets = JsonManager.load_json('resources/input.json')
80
-
81
- if input_option == 'local':
82
- metadata_file_path = os.path.join(input_dir, f'{metadata}.txt')
83
- metadata_provided = os.path.isfile(metadata_file_path)
84
- if metadata_provided:
85
- with open(metadata_file_path, encoding='utf-8') as f:
86
- metadata_provided = True if f.read() else False
87
- else:
88
- metadata_provided = input_presets[input_option]['metadata_provides'][metadata]
89
-
90
- return metadata_provided
91
-
92
- @staticmethod
93
- def check_metadata_required(output_option: str, metadata: str) -> bool:
94
- # metadata = 'title' or 'author'
95
- output_presets = JsonManager.load_json('resources/output.json')
96
- return output_presets[output_option]['metadata_requirements'][metadata]
97
-
98
- @staticmethod
99
- def generate_emoji_file(dir: str, default_emoji: str = ''):
100
- emoji_path = os.path.join(dir, 'emoji.txt')
101
- emoji_dict = None
102
- if os.path.isfile(emoji_path):
103
- with open(emoji_path , "r", encoding='utf-8') as f:
104
- emoji_dict = json.load(f)
105
-
106
- emoji_dict_new = {}
107
- for file in sorted(os.listdir(dir)):
108
- if not os.path.isfile(os.path.join(dir, file)) and CodecInfo.get_file_ext(file) in ('.txt', '.m4a'):
109
- continue
110
- file_name = os.path.splitext(file)[0]
111
- if emoji_dict and file_name in emoji_dict:
112
- emoji_dict_new[file_name] = emoji_dict[file_name]
113
- else:
114
- emoji_dict_new[file_name] = default_emoji
115
-
116
- with open(emoji_path, 'w+', encoding='utf-8') as f:
117
- json.dump(emoji_dict_new, f, indent=4, ensure_ascii=False)
118
-
119
- @staticmethod
120
- def split_sticker_packs(dir: str, title: str, file_per_pack: Optional[int] = None, file_per_anim_pack: Optional[int] = None, file_per_image_pack: Optional[int] = None, separate_image_anim: bool = True) -> dict:
121
- # {pack_1: [sticker1_path, sticker2_path]}
122
- packs = {}
123
-
124
- if file_per_pack == None:
125
- file_per_pack = file_per_anim_pack if file_per_anim_pack != None else file_per_image_pack
126
- else:
127
- file_per_anim_pack = file_per_pack
128
- file_per_image_pack = file_per_pack
129
-
130
- stickers_present = MetadataHandler.get_stickers_present(dir)
131
-
132
- processed = 0
133
-
134
- if separate_image_anim == True:
135
- image_stickers = []
136
- anim_stickers = []
137
-
138
- image_pack_count = 0
139
- anim_pack_count = 0
140
-
141
- anim_present = False
142
- image_present = False
143
-
144
- for file in stickers_present:
145
- file_path = os.path.join(dir, file)
146
-
147
- if CodecInfo.is_anim(file_path):
148
- anim_stickers.append(file_path)
149
- else:
150
- image_stickers.append(file_path)
151
-
152
- anim_present = anim_present or len(anim_stickers) > 0
153
- image_present = image_present or len(image_stickers) > 0
154
-
155
- processed += 1
156
- finished_all = True if processed == len(stickers_present) else False
157
-
158
- if len(anim_stickers) == file_per_anim_pack or (finished_all and len(anim_stickers) > 0):
159
- suffix = f'{"-anim" if image_present else ""}{"-" + str(anim_pack_count) if anim_pack_count > 0 else ""}'
160
- title_current = str(title) + suffix
161
- packs[title_current] = anim_stickers.copy()
162
- anim_stickers = []
163
- anim_pack_count += 1
164
- if len(image_stickers) == file_per_image_pack or (finished_all and len(image_stickers) > 0):
165
- suffix = f'{"-image" if anim_present else ""}{"-" + str(image_pack_count) if image_pack_count > 0 else ""}'
166
- title_current = str(title) + suffix
167
- packs[title_current] = image_stickers.copy()
168
- image_stickers = []
169
- image_pack_count += 1
170
-
171
- else:
172
- stickers = []
173
- pack_count = 0
174
-
175
- for file in stickers_present:
176
- file_path = os.path.join(dir, file)
177
-
178
- stickers.append(file_path)
179
-
180
- processed += 1
181
- finished_all = True if processed == len(stickers_present) else False
182
-
183
- if len(stickers) == file_per_pack or (finished_all and len(stickers) > 0):
184
- suffix = f'{"-" + str(pack_count) if pack_count > 0 else ""}'
185
- title = str(title) + suffix
186
- packs[title] = stickers.copy()
187
- stickers = []
188
- pack_count += 1
189
-
190
- return packs
@@ -1,46 +0,0 @@
1
- #!/usr/bin/env python3
2
- import subprocess
3
- import os
4
- import shutil
5
- import platform
6
- from typing import Union, AnyStr
7
-
8
- class RunBin:
9
- @staticmethod
10
- def get_bin(bin: str, silent: bool = False, cb_msg=print) -> Union[str, AnyStr, None]:
11
- if os.path.isfile(bin):
12
- return bin
13
-
14
- if platform.system() == 'Windows':
15
- bin = bin + '.exe'
16
-
17
- which_result = shutil.which(bin)
18
- if which_result != None:
19
- return os.path.abspath(which_result) # type: ignore[type-var]
20
- elif silent == False:
21
- cb_msg(f'Warning: Cannot find binary file {bin}')
22
-
23
- return None
24
-
25
- @staticmethod
26
- def run_cmd(cmd_list: list[str], silence: bool = False, cb_msg=print) -> Union[bool, str]:
27
- bin_path = RunBin.get_bin(cmd_list[0]) # type: ignore[assignment]
28
-
29
- if bin_path:
30
- cmd_list[0] = bin_path
31
- else:
32
- if silence == False:
33
- cb_msg(f"Error while executing {' '.join(cmd_list)} : Command not found")
34
- return False
35
-
36
- # sp = subprocess.Popen(cmd_list, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
37
- sp = subprocess.run(cmd_list, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
38
-
39
- output_str = sp.stdout.decode()
40
- error_str = sp.stderr.decode()
41
-
42
- if silence == False and error_str != '':
43
- cb_msg(f"Error while executing {' '.join(cmd_list)} : {error_str}")
44
- return False
45
-
46
- return output_str