sticker-convert 2.8.13__py3-none-any.whl → 2.9.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/cli.py CHANGED
@@ -17,6 +17,7 @@ from sticker_convert.job_option import CompOption, CredOption, InputOption, Outp
17
17
  from sticker_convert.utils.auth.get_kakao_auth import GetKakaoAuth
18
18
  from sticker_convert.utils.auth.get_line_auth import GetLineAuth
19
19
  from sticker_convert.utils.auth.get_signal_auth import GetSignalAuth
20
+ from sticker_convert.utils.auth.get_viber_auth import GetViberAuth
20
21
  from sticker_convert.utils.callback import Callback
21
22
  from sticker_convert.utils.files.json_manager import JsonManager
22
23
  from sticker_convert.utils.url_detect import UrlDetect
@@ -452,6 +453,9 @@ class CLI:
452
453
  line_cookies=args.line_cookies
453
454
  if args.line_cookies
454
455
  else creds.get("line", {}).get("cookies"),
456
+ viber_auth=args.viber_auth
457
+ if args.viber_auth
458
+ else creds.get("viber", {}).get("auth"),
455
459
  )
456
460
 
457
461
  if args.kakao_get_auth:
@@ -501,6 +505,20 @@ class CLI:
501
505
  "Failed to get Line cookies. Have you logged in the web browser?"
502
506
  )
503
507
 
508
+ if args.viber_get_auth:
509
+ get_viber_auth = GetViberAuth(self.cb.ask_str)
510
+
511
+ viber_bin_path = None
512
+ if args.viber_bin_path:
513
+ viber_bin_path = args.viber_bin_path
514
+
515
+ viber_auth, msg = get_viber_auth.get_cred(viber_bin_path)
516
+
517
+ if viber_auth:
518
+ opt_cred.viber_auth = viber_auth
519
+
520
+ self.cb.msg(msg)
521
+
504
522
  if args.save_cred:
505
523
  creds_path = CONFIG_DIR / "creds.json"
506
524
  JsonManager.save_json(creds_path, opt_cred.to_dict())
@@ -3,13 +3,13 @@ from __future__ import annotations
3
3
 
4
4
  import itertools
5
5
  import json
6
+ import re
6
7
  import zipfile
7
8
  from io import BytesIO
8
9
  from pathlib import Path
9
10
  from typing import Any, List, Optional, Tuple, cast
10
11
  from urllib.parse import urlparse
11
12
 
12
- import js2py # type: ignore
13
13
  import requests
14
14
  from bs4 import BeautifulSoup
15
15
  from bs4.element import Tag
@@ -47,7 +47,7 @@ class MetadataKakao:
47
47
  headers = {"User-Agent": "Android"}
48
48
 
49
49
  response = requests.get(url, headers=headers)
50
- soup = BeautifulSoup(response.text, "html.parser")
50
+ soup = BeautifulSoup(response.content.decode("utf-8", "ignore"), "html.parser")
51
51
 
52
52
  pack_title_tag = soup.find("title") # type: ignore
53
53
  if not pack_title_tag:
@@ -72,17 +72,39 @@ class MetadataKakao:
72
72
  js = js[func_start_pos:]
73
73
  bracket_start_pos = js.find("{")
74
74
  func_end_pos = search_bracket(js[bracket_start_pos:]) + bracket_start_pos
75
- js = js[: func_end_pos + 1]
76
- web2app_start_pos = js.find("daumtools.web2app(")
77
- js = js[:web2app_start_pos] + "return a;}"
78
- get_item_code = js2py.eval_js(js) # type: ignore
79
- kakao_scheme_link = cast(
80
- str,
81
- get_item_code(
82
- "kakaotalk://store/emoticon/${i}?referer=share_link", item_code_fake
83
- ),
84
- )
85
- item_code = urlparse(kakao_scheme_link).path.split("/")[-1]
75
+ js = js[bracket_start_pos + 1 : func_end_pos]
76
+ js = js.split(";")[0]
77
+
78
+ minus_num_regex = re.search(r"\-(.*?)\^", js)
79
+ if not minus_num_regex:
80
+ return None, None
81
+ minus_num_str = minus_num_regex.group(1)
82
+ if not minus_num_str.isnumeric():
83
+ return None, None
84
+ minus_num = int(minus_num_str)
85
+
86
+ xor_num_regex = re.search(r"\^(.*?)\)", js)
87
+ if not xor_num_regex:
88
+ return None, None
89
+ xor_num_str = xor_num_regex.group(1)
90
+ if not xor_num_str.isnumeric():
91
+ return None, None
92
+ xor_num = int(xor_num_str)
93
+
94
+ item_code = str(int(item_code_fake) - minus_num ^ xor_num)
95
+
96
+ # https://github.com/Nuitka/Nuitka/issues/385
97
+ # js2py not working if compiled by nuitka
98
+ # web2app_start_pos = js.find("daumtools.web2app(")
99
+ # js = js[:web2app_start_pos] + "return a;}"
100
+ # get_item_code = js2py.eval_js(js) # type: ignore
101
+ # kakao_scheme_link = cast(
102
+ # str,
103
+ # get_item_code(
104
+ # "kakaotalk://store/emoticon/${i}?referer=share_link", item_code_fake
105
+ # ),
106
+ # )
107
+ # item_code = urlparse(kakao_scheme_link).path.split("/")[-1]
86
108
 
87
109
  return pack_title, item_code
88
110
 
sticker_convert/gui.py CHANGED
@@ -159,6 +159,8 @@ class GUI(Window):
159
159
  self.kakao_country_code_var = StringVar(self)
160
160
  self.kakao_phone_number_var = StringVar(self)
161
161
  self.line_cookies_var = StringVar(self)
162
+ self.viber_auth_var = StringVar(self)
163
+ self.viber_bin_path_var = StringVar(self)
162
164
 
163
165
  # Config
164
166
  self.settings_save_cred_var = BooleanVar()
@@ -385,6 +387,7 @@ class GUI(Window):
385
387
  self.creds.get("kakao", {}).get("phone_number", "")
386
388
  )
387
389
  self.line_cookies_var.set(self.creds.get("line", {}).get("cookies", ""))
390
+ self.viber_auth_var.set(self.creds.get("viber", {}).get("auth", ""))
388
391
 
389
392
  def get_input_name(self) -> str:
390
393
  return [
@@ -545,6 +548,7 @@ class GUI(Window):
545
548
  kakao_country_code=self.kakao_country_code_var.get(),
546
549
  kakao_phone_number=self.kakao_phone_number_var.get(),
547
550
  line_cookies=self.line_cookies_var.get(),
551
+ viber_auth=self.viber_auth_var.get(),
548
552
  )
549
553
 
550
554
  def start_process(self) -> None:
@@ -771,6 +775,11 @@ class GUI(Window):
771
775
  else:
772
776
  self.cred_frame.telegram_userid_entry.config(bootstyle="default") # type: ignore
773
777
 
778
+ if output_option == "viber" and not self.viber_auth_var.get():
779
+ self.cred_frame.viber_auth_entry.config(bootstyle="warning") # type: ignore
780
+ else:
781
+ self.cred_frame.viber_auth_entry.config(bootstyle="default") # type: ignore
782
+
774
783
  if (
775
784
  urlparse(url).netloc == "e.kakao.com"
776
785
  and not self.kakao_auth_token_var.get()
@@ -8,6 +8,7 @@ from sticker_convert.gui_components.frames.right_clicker import RightClicker
8
8
  from sticker_convert.gui_components.windows.kakao_get_auth_window import KakaoGetAuthWindow
9
9
  from sticker_convert.gui_components.windows.line_get_auth_window import LineGetAuthWindow
10
10
  from sticker_convert.gui_components.windows.signal_get_auth_window import SignalGetAuthWindow
11
+ from sticker_convert.gui_components.windows.viber_get_auth_window import ViberGetAuthWindow
11
12
 
12
13
  if TYPE_CHECKING:
13
14
  from sticker_convert.gui import GUI # type: ignore
@@ -103,6 +104,20 @@ class CredFrame(LabelFrame):
103
104
  bootstyle="secondary", # type: ignore
104
105
  )
105
106
 
107
+ self.viber_auth_lbl = Label(
108
+ self, text="Viber auth", width=18, justify="left", anchor="w"
109
+ )
110
+ self.viber_auth_entry = Entry(
111
+ self, textvariable=self.gui.viber_auth_var, width=35
112
+ )
113
+ self.viber_auth_entry.bind("<Button-3><ButtonRelease-3>", RightClicker)
114
+ self.viber_get_auth_btn = Button(
115
+ self,
116
+ text="Generate",
117
+ command=self.cb_viber_get_auth,
118
+ bootstyle="secondary", # type: ignore
119
+ )
120
+
106
121
  self.help_btn = Button(
107
122
  self,
108
123
  text="Get help",
@@ -133,6 +148,9 @@ class CredFrame(LabelFrame):
133
148
  self.line_cookies_lbl.grid(column=0, row=6, sticky="w", padx=3, pady=3)
134
149
  self.line_cookies_entry.grid(column=1, row=6, sticky="w", padx=3, pady=3)
135
150
  self.line_get_auth_btn.grid(column=2, row=6, sticky="e", padx=3, pady=3)
151
+ self.viber_auth_lbl.grid(column=0, row=7, sticky="w", padx=3, pady=3)
152
+ self.viber_auth_entry.grid(column=1, row=7, sticky="w", padx=3, pady=3)
153
+ self.viber_get_auth_btn.grid(column=2, row=7, sticky="e", padx=3, pady=3)
136
154
  self.help_btn.grid(column=2, row=8, sticky="e", padx=3, pady=3)
137
155
 
138
156
  def cb_cred_help(self, *_: Any) -> None:
@@ -150,6 +168,9 @@ class CredFrame(LabelFrame):
150
168
  def cb_line_get_auth(self, *_: Any) -> None:
151
169
  LineGetAuthWindow(self.gui)
152
170
 
171
+ def cb_viber_get_auth(self, *_: Any) -> None:
172
+ ViberGetAuthWindow(self.gui)
173
+
153
174
  def set_states(self, state: str) -> None:
154
175
  self.signal_uuid_entry.config(state=state)
155
176
  self.signal_password_entry.config(state=state)
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env python3
2
+ import platform
3
+ from functools import partial
4
+ from pathlib import Path
5
+ from subprocess import Popen
6
+ from tkinter import filedialog
7
+ from typing import Any
8
+
9
+ from ttkbootstrap import Button, Entry, Frame, Label # type: ignore
10
+
11
+ from sticker_convert.gui_components.gui_utils import GUIUtils
12
+ from sticker_convert.gui_components.windows.base_window import BaseWindow
13
+ from sticker_convert.utils.auth.get_viber_auth import GetViberAuth
14
+
15
+
16
+ class ViberGetAuthWindow(BaseWindow):
17
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
18
+ super().__init__(*args, **kwargs)
19
+
20
+ self.title("Get Viber auth data")
21
+
22
+ self.cb_msg_block_viber = partial(self.gui.cb_msg_block, parent=self)
23
+ self.cb_ask_str_viber = partial(self.gui.cb_ask_str, parent=self)
24
+
25
+ self.frame_info = Frame(self.scrollable_frame)
26
+ self.frame_btns = Frame(self.scrollable_frame)
27
+ self.frame_config = Frame(self.scrollable_frame)
28
+
29
+ self.frame_info.grid(column=0, row=0, sticky="news", padx=3, pady=3)
30
+ self.frame_btns.grid(column=0, row=1, sticky="news", padx=3, pady=3)
31
+ self.frame_config.grid(column=0, row=2, sticky="news", padx=3, pady=3)
32
+
33
+ # Info frame
34
+ self.explanation_lbl0 = Label(
35
+ self.frame_info,
36
+ text="Please install Viber Desktop and login first.",
37
+ justify="left",
38
+ anchor="w",
39
+ )
40
+ self.explanation_lbl1 = Label(
41
+ self.frame_info,
42
+ text="It may take a minute to get auth data.",
43
+ justify="left",
44
+ anchor="w",
45
+ )
46
+ self.explanation_lbl2 = None
47
+ if platform.system() == "Darwin":
48
+ self.explanation_lbl2 = Label(
49
+ self.frame_info,
50
+ text="You need to disable SIP and may be asked for user password.",
51
+ justify="left",
52
+ anchor="w",
53
+ )
54
+
55
+ self.explanation_lbl0.grid(column=0, row=0, sticky="w", padx=3, pady=3)
56
+ self.explanation_lbl1.grid(column=0, row=1, sticky="w", padx=3, pady=3)
57
+ if self.explanation_lbl2 is not None:
58
+ self.explanation_lbl2.grid(column=0, row=2, sticky="w", padx=3, pady=3)
59
+
60
+ # Start button frame
61
+ self.launch_btn = Button(
62
+ self.frame_btns,
63
+ text="Launch Viber Desktop",
64
+ command=self.cb_launch_viber,
65
+ bootstyle="secondary", # type: ignore
66
+ )
67
+
68
+ self.get_cred_btn = Button(
69
+ self.frame_btns,
70
+ text="Get auth data",
71
+ command=self.cb_get_cred,
72
+ bootstyle="default", # type: ignore
73
+ )
74
+
75
+ self.launch_btn.pack()
76
+ self.get_cred_btn.pack()
77
+
78
+ # Config frame
79
+ self.setdir_lbl = Label(
80
+ self.frame_config,
81
+ text=self.gui.help["cred"]["viber_bin_path"],
82
+ justify="left",
83
+ anchor="w",
84
+ )
85
+
86
+ self.setdir_entry = Entry(
87
+ self.frame_config,
88
+ textvariable=self.gui.viber_bin_path_var,
89
+ width=32,
90
+ )
91
+ self.setdir_btn = Button(
92
+ self.frame_config,
93
+ text="Choose",
94
+ command=self.cb_setdir,
95
+ width=8,
96
+ bootstyle="secondary", # type: ignore
97
+ )
98
+
99
+ self.setdir_lbl.grid(column=0, row=0, columnspan=2, sticky="w", padx=3, pady=3)
100
+ self.setdir_entry.grid(column=0, row=1, sticky="w", padx=3, pady=3)
101
+ self.setdir_btn.grid(column=1, row=1, sticky="e", padx=3, pady=3)
102
+
103
+ GUIUtils.finalize_window(self)
104
+
105
+ def cb_get_cred(self) -> None:
106
+ m = GetViberAuth(self.cb_ask_str_viber)
107
+
108
+ viber_bin_path = None
109
+ if self.gui.viber_bin_path_var.get():
110
+ viber_bin_path = self.gui.viber_bin_path_var.get()
111
+
112
+ viber_auth, msg = m.get_cred(viber_bin_path)
113
+
114
+ if viber_auth:
115
+ if not self.gui.creds.get("viber"):
116
+ self.gui.creds["viber"] = {}
117
+ self.gui.creds["viber"]["auth"] = viber_auth
118
+ self.gui.viber_auth_var.set(viber_auth)
119
+
120
+ self.gui.save_creds()
121
+ self.gui.highlight_fields()
122
+
123
+ self.cb_msg_block_viber(msg)
124
+
125
+ def cb_launch_viber(self) -> None:
126
+ m = GetViberAuth(self.cb_ask_str_viber)
127
+ viber_bin_path = m.get_viber_desktop()
128
+
129
+ if self.gui.viber_auth_var.get():
130
+ viber_bin_path = self.gui.viber_auth_var.get()
131
+
132
+ if viber_bin_path:
133
+ Popen([viber_bin_path])
134
+ else:
135
+ self.cb_msg_block_viber("Error: Viber Desktop not installed.")
136
+
137
+ def cb_setdir(self) -> None:
138
+ orig_input_dir = self.gui.viber_bin_path_var.get()
139
+ if not Path(orig_input_dir).is_dir():
140
+ orig_input_dir = ""
141
+ input_dir = filedialog.askdirectory(initialdir=orig_input_dir)
142
+ if input_dir:
143
+ self.gui.viber_bin_path_var.set(input_dir)
sticker_convert/job.py CHANGED
@@ -21,6 +21,7 @@ from sticker_convert.job_option import CompOption, CredOption, InputOption, Outp
21
21
  from sticker_convert.uploaders.compress_wastickers import CompressWastickers
22
22
  from sticker_convert.uploaders.upload_signal import UploadSignal
23
23
  from sticker_convert.uploaders.upload_telegram import UploadTelegram
24
+ from sticker_convert.uploaders.upload_viber import UploadViber
24
25
  from sticker_convert.uploaders.xcode_imessage import XcodeImessage
25
26
  from sticker_convert.utils.callback import CallbackReturn, CbQueueType, ResultsListType, WorkQueueType
26
27
  from sticker_convert.utils.files.json_resources_loader import OUTPUT_JSON
@@ -305,6 +306,10 @@ class Job:
305
306
  error_msg += "[X] Uploading to signal requires uuid and password.\n"
306
307
  error_msg += save_to_local_tip
307
308
 
309
+ if self.opt_output.option == "viber" and not self.opt_cred.viber_auth:
310
+ error_msg += "[X] Uploading to Viber requires auth data.\n"
311
+ error_msg += save_to_local_tip
312
+
308
313
  output_presets = OUTPUT_JSON
309
314
 
310
315
  input_option = self.opt_input.option
@@ -656,6 +661,9 @@ class Job:
656
661
  if self.opt_output.option == "imessage":
657
662
  exporters.append(XcodeImessage.start)
658
663
 
664
+ if self.opt_output.option == "viber":
665
+ exporters.append(UploadViber.start)
666
+
659
667
  self.executor.start_workers(processes=1)
660
668
 
661
669
  for exporter in exporters:
@@ -222,6 +222,7 @@ class CredOption(BaseOption):
222
222
  kakao_country_code: str = ""
223
223
  kakao_phone_number: str = ""
224
224
  line_cookies: str = ""
225
+ viber_auth: str = ""
225
226
 
226
227
  def to_dict(self) -> Dict[Any, Any]:
227
228
  return {
@@ -235,4 +236,5 @@ class CredOption(BaseOption):
235
236
  "phone_number": self.kakao_phone_number,
236
237
  },
237
238
  "line": {"cookies": self.line_cookies},
239
+ "viber": {"auth": self.viber_auth},
238
240
  }
@@ -338,8 +338,8 @@
338
338
  "vid": ".png"
339
339
  },
340
340
  "fps": {
341
- "min": 1,
342
- "max": 1,
341
+ "min": 0,
342
+ "max": 0,
343
343
  "power": 1
344
344
  },
345
345
  "res": {
@@ -69,6 +69,9 @@
69
69
  "kakao_phone_number": "Set Kakao phone number (Phone number associated with your Kakao account)\nDo NOT enter country code\nExample: 7700900142\nUsed for send / receive verification code via SMS.\nRequired for generating Kakao auth_token.",
70
70
  "line_get_auth": "Get Line cookies from browser, which is required to create custom message stickers.",
71
71
  "line_cookies": "Set Line cookies, which is required to create custom message stickers.",
72
+ "viber_auth": "Set Viber authentication data.\nRequired for uploading Viber stickers.",
73
+ "viber_get_auth": "Generate Viber authentication data.",
74
+ "viber_bin_path": "Specify location of Viber Desktop application.\nUseful for portable installation.",
72
75
  "save_cred": "Save Signal and Telegram credentials."
73
76
  }
74
77
  }
@@ -0,0 +1,26 @@
1
+ #!/bin/bash
2
+ # Reference: https://github.com/hajzer/bash-memory-dump
3
+
4
+ OS_PAGESIZE=`getconf PAGESIZE`
5
+
6
+ PID=$1
7
+ PID_MAPS=/proc/$PID/maps
8
+ PID_MEM=/proc/$PID/mem
9
+
10
+ rm -f /tmp/viber.dmp.$PID
11
+ grep rw-p $PID_MAPS |
12
+ while IFS='' read -r line || [[ -n "$line" ]]; do
13
+ range=`echo $line | awk '{print $1;}'`
14
+
15
+ vma_start=$(( 0x`echo $range | cut -d- -f1` ))
16
+ vma_end=$(( 0x`echo $range | cut -d- -f2` ))
17
+ vma_size=$(( $vma_end - $vma_start ))
18
+
19
+ dd_start=$(( $vma_start / $OS_PAGESIZE ))
20
+ dd_bs=$OS_PAGESIZE
21
+ dd_count=$(( $vma_size / $OS_PAGESIZE ))
22
+
23
+ set +e
24
+ dd if="$PID_MEM" bs="$dd_bs" skip="$dd_start" count="$dd_count"
25
+ set -e
26
+ done
@@ -23,6 +23,14 @@
23
23
  "author": false
24
24
  }
25
25
  },
26
+ "viber": {
27
+ "full_name": "Upload to Viber",
28
+ "help": "Upload to Viber",
29
+ "metadata_requirements": {
30
+ "title": true,
31
+ "author": false
32
+ }
33
+ },
26
34
  "whatsapp": {
27
35
  "full_name": "Compress to .wastickers (WhatsApp)",
28
36
  "help": "Create a .wastickers file for uploading to WhatsApp",
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env python3
2
+ import copy
3
+ import json
4
+ import shutil
5
+ import zipfile
6
+ from pathlib import Path
7
+ from typing import Any, Dict, List
8
+
9
+ import requests
10
+
11
+ from sticker_convert.converter import StickerConvert
12
+ from sticker_convert.job_option import CompOption, CredOption, OutputOption
13
+ from sticker_convert.uploaders.upload_base import UploadBase
14
+ from sticker_convert.utils.callback import CallbackProtocol, CallbackReturn
15
+ from sticker_convert.utils.files.cache_store import CacheStore
16
+ from sticker_convert.utils.files.metadata_handler import MetadataHandler
17
+ from sticker_convert.utils.files.sanitize_filename import sanitize_filename
18
+ from sticker_convert.utils.media.format_verify import FormatVerify
19
+
20
+
21
+ class UploadViber(UploadBase):
22
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
23
+ super().__init__(*args, **kwargs)
24
+
25
+ self.base_spec.set_size_max(0)
26
+ self.base_spec.square = True
27
+
28
+ self.png_spec = copy.deepcopy(self.base_spec)
29
+ self.png_spec.set_res_max(490)
30
+ self.png_spec.set_format((".png",))
31
+
32
+ self.png_cover_spec = copy.deepcopy(self.base_spec)
33
+ self.png_cover_spec.set_res_max(120)
34
+ self.png_spec.set_format((".png",))
35
+
36
+ self.opt_comp_merged = copy.deepcopy(self.opt_comp)
37
+ self.opt_comp_merged.merge(self.png_spec)
38
+
39
+ def upload_stickers_viber(self) -> List[str]:
40
+ urls: List[str] = []
41
+
42
+ if not self.opt_cred.viber_auth:
43
+ self.cb.put("Viber auth required for uploading to viber")
44
+ return urls
45
+
46
+ upload_data_base: Dict[str, str] = {}
47
+ for i in self.opt_cred.viber_auth.split(";"):
48
+ j = i.split(":")
49
+ upload_data_base[j[0]] = j[1]
50
+
51
+ if upload_data_base.get("member_id") is None:
52
+ self.cb.put("Invalid Viber auth: Missing member_id")
53
+ return urls
54
+ if upload_data_base.get("m_token") is None:
55
+ self.cb.put("Invalid Viber auth: Missing m_token")
56
+ return urls
57
+ if upload_data_base.get("m_ts") is None:
58
+ self.cb.put("Invalid Viber auth: Missing m_ts")
59
+ return urls
60
+
61
+ title, author, _ = MetadataHandler.get_metadata(
62
+ self.opt_output.dir,
63
+ title=self.opt_output.title,
64
+ author=self.opt_output.author,
65
+ )
66
+ if title is None:
67
+ raise TypeError(f"title cannot be {title}")
68
+ if author is None:
69
+ author = ""
70
+
71
+ packs = MetadataHandler.split_sticker_packs(
72
+ self.opt_output.dir,
73
+ title=title,
74
+ file_per_pack=24,
75
+ separate_image_anim=False,
76
+ )
77
+
78
+ cover_path_old = MetadataHandler.get_cover(self.opt_output.dir)
79
+ if cover_path_old:
80
+ cover_path = cover_path_old
81
+ else:
82
+ cover_path_old = MetadataHandler.get_stickers_present(self.opt_output.dir)[
83
+ 0
84
+ ]
85
+ cover_path = self.opt_output.dir / "cover.png"
86
+
87
+ if not FormatVerify.check_file(cover_path_old, spec=self.png_cover_spec):
88
+ StickerConvert.convert(
89
+ cover_path_old,
90
+ cover_path,
91
+ self.opt_comp_merged,
92
+ self.cb,
93
+ self.cb_return,
94
+ )
95
+
96
+ for pack_title, stickers in packs.items():
97
+ with CacheStore.get_cache_store(path=self.opt_comp.cache_dir) as tempdir:
98
+ for num, src in enumerate(stickers):
99
+ self.cb.put(f"Verifying {src} for uploading to Viber")
100
+
101
+ dst = Path(tempdir, f"{str(num).zfill(2)}.png")
102
+
103
+ if FormatVerify.check_file(src, spec=self.png_spec):
104
+ shutil.copy(src, dst)
105
+ else:
106
+ StickerConvert.convert(
107
+ Path(src),
108
+ Path(dst),
109
+ self.opt_comp_merged,
110
+ self.cb,
111
+ self.cb_return,
112
+ )
113
+
114
+ out_f = Path(
115
+ self.opt_output.dir, sanitize_filename(pack_title + ".zip")
116
+ ).as_posix()
117
+
118
+ with zipfile.ZipFile(out_f, "w", zipfile.ZIP_DEFLATED) as zipf:
119
+ for file in Path(tempdir).iterdir():
120
+ file_path = Path(tempdir, file.name)
121
+ zipf.write(file_path, arcname=file_path.name)
122
+
123
+ upload_data = copy.deepcopy(upload_data_base)
124
+ upload_data["title"] = pack_title
125
+ upload_data["description"] = author
126
+ upload_data["shareable"] = "1"
127
+
128
+ with open(out_f, "rb") as f, open(cover_path, "rb") as g:
129
+ r = requests.post(
130
+ "https://market.api.viber.com/2/users/custom-sticker-packs/create",
131
+ files={
132
+ "file": ("upload.zip", f),
133
+ "file_icon": ("color_icon.png", g),
134
+ },
135
+ data=upload_data,
136
+ )
137
+
138
+ if r.ok:
139
+ rjson = json.loads(r.text)
140
+ if rjson["status"] == 1:
141
+ pack_id = rjson["custom_sticker_pack"]["id"]
142
+ url = f"https://stickers.viber.com/pages/custom-sticker-packs/{pack_id}"
143
+ urls.append(url)
144
+ self.cb.put(f"Uploaded {pack_title}")
145
+ else:
146
+ self.cb.put(
147
+ f"Failed to upload {pack_title}: {r.status_code} {r.text}"
148
+ )
149
+ if rjson["status"] == 103:
150
+ self.cb.put(
151
+ "Viber auth data may have expired. Try to regenerate it?"
152
+ )
153
+ else:
154
+ self.cb.put(f"Failed to upload {pack_title}: {r.status_code} {r.text}")
155
+
156
+ return urls
157
+
158
+ @staticmethod
159
+ def start(
160
+ opt_output: OutputOption,
161
+ opt_comp: CompOption,
162
+ opt_cred: CredOption,
163
+ cb: CallbackProtocol,
164
+ cb_return: CallbackReturn,
165
+ ) -> List[str]:
166
+ exporter = UploadViber(opt_output, opt_comp, opt_cred, cb, cb_return)
167
+ return exporter.upload_stickers_viber()
@@ -0,0 +1,315 @@
1
+ #!/usr/bin/env python3
2
+ import os
3
+ import platform
4
+ import shutil
5
+ import subprocess
6
+ import time
7
+ from getpass import getpass
8
+ from pathlib import Path
9
+ from typing import Callable, Optional, Tuple, cast
10
+
11
+ from sticker_convert.definitions import ROOT_DIR
12
+
13
+ # psutil is missing on arm64 linux appimage
14
+ # Note: There is no Viber Desktop on arm64 linux anyway
15
+ try:
16
+ import psutil
17
+
18
+ PSUTIL_LOADED = True
19
+ except ModuleNotFoundError:
20
+ PSUTIL_LOADED = False # type: ignore
21
+
22
+ MSG_NO_BIN = """Viber Desktop not detected.
23
+ Download and install Viber Desktop,
24
+ then login to Viber Desktop and try again."""
25
+
26
+ MSG_NO_AUTH = """Viber Desktop installed,
27
+ but viber_auth not found.
28
+ Please login to Viber Desktop and try again."""
29
+
30
+ MSG_SIP_ENABLED = """You need to disable SIP:
31
+ 1. Restart computer in Recovery mode
32
+ 2. Launch Terminal from the Utilities menu
33
+ 3. Run the command `csrutil disable`
34
+ 4. Restart your computer"""
35
+
36
+ MSG_NO_PSUTIL = "Python package psutil is necessary"
37
+
38
+
39
+ def killall(name: str) -> bool:
40
+ if not PSUTIL_LOADED:
41
+ return False
42
+
43
+ result = False
44
+
45
+ for proc in psutil.process_iter(): # type: ignore
46
+ if name in proc.name().lower():
47
+ proc.kill()
48
+ result = True
49
+
50
+ return result
51
+
52
+
53
+ def find_pid_by_name(name: str) -> Optional[int]:
54
+ if not PSUTIL_LOADED:
55
+ return None
56
+
57
+ for proc in psutil.process_iter(): # type: ignore
58
+ if name in proc.name().lower():
59
+ return proc.pid
60
+
61
+ return None
62
+
63
+
64
+ class GetViberAuth:
65
+ def __init__(self, cb_ask_str: Callable[..., str] = input):
66
+ self.cb_ask_str = cb_ask_str
67
+
68
+ def get_auth_windows(self, viber_bin_path: str) -> Tuple[Optional[str], str]:
69
+ if not PSUTIL_LOADED:
70
+ return None, MSG_NO_PSUTIL
71
+
72
+ member_id = None
73
+ m_token = None
74
+ m_ts = None
75
+
76
+ killed = killall("viber")
77
+ if killed:
78
+ time.sleep(5)
79
+ subprocess.Popen([viber_bin_path])
80
+ time.sleep(10)
81
+
82
+ from PyMemoryEditor import OpenProcess # type: ignore
83
+
84
+ viber_pid = find_pid_by_name("viber")
85
+ with OpenProcess(pid=viber_pid) as process:
86
+ for address in process.search_by_value(str, 18, "X-Viber-Auth-Mid: "): # type: ignore
87
+ member_id_addr = cast(int, address) + 18
88
+ member_id_bytes = process.read_process_memory(member_id_addr, bytes, 20)
89
+ member_id_term = member_id_bytes.find(b"\x0d\x0a")
90
+ if member_id_term == -1:
91
+ continue
92
+ member_id = member_id_bytes[:member_id_term].decode(encoding="ascii")
93
+ break
94
+ if member_id is None:
95
+ return None, MSG_NO_AUTH
96
+
97
+ for address in process.search_by_value(str, 20, "X-Viber-Auth-Token: "): # type: ignore
98
+ m_token_addr = cast(int, address) + 20
99
+ m_token = process.read_process_memory(m_token_addr, str, 64)
100
+ break
101
+ if m_token is None:
102
+ return None, MSG_NO_AUTH
103
+
104
+ for address in process.search_by_value(str, 24, "X-Viber-Auth-Timestamp: "): # type: ignore
105
+ m_ts_addr = cast(int, address) + 24
106
+ m_ts = process.read_process_memory(m_ts_addr, str, 13)
107
+ break
108
+ if m_ts is None:
109
+ return None, MSG_NO_AUTH
110
+
111
+ killall("viber")
112
+
113
+ viber_auth = f"member_id:{member_id};m_token:{m_token};m_ts:{m_ts}"
114
+ msg = "Got viber_auth successfully:\n"
115
+ msg += f"{viber_auth=}\n"
116
+
117
+ return viber_auth, msg
118
+
119
+ def get_auth_linux(self, viber_bin_path: str) -> Tuple[Optional[str], str]:
120
+ if not PSUTIL_LOADED:
121
+ return None, MSG_NO_PSUTIL
122
+
123
+ member_id = None
124
+ m_token = None
125
+ m_ts = None
126
+
127
+ killed = killall("viber")
128
+ if killed:
129
+ time.sleep(5)
130
+ subprocess.Popen([viber_bin_path])
131
+ time.sleep(10)
132
+
133
+ viber_pid = find_pid_by_name("viber")
134
+ memdump_sh_path = (ROOT_DIR / "resources/memdump.sh").as_posix()
135
+
136
+ s = subprocess.run(
137
+ [
138
+ memdump_sh_path,
139
+ str(viber_pid),
140
+ ],
141
+ capture_output=True,
142
+ ).stdout
143
+
144
+ if s.find(b"X-Viber-Auth-Mid: ") != -1:
145
+ pass
146
+ elif shutil.which("pkexec") and os.getenv("DISPLAY"):
147
+ s = subprocess.run(
148
+ [
149
+ "pkexec",
150
+ memdump_sh_path,
151
+ str(viber_pid),
152
+ ],
153
+ capture_output=True,
154
+ ).stdout
155
+ else:
156
+ prompt = "Enter sudo password: "
157
+ if self.cb_ask_str != input:
158
+ sudo_password = self.cb_ask_str(
159
+ prompt, initialvalue="", cli_show_initialvalue=False
160
+ )
161
+ else:
162
+ sudo_password = getpass(prompt)
163
+ sudo_password_pipe = subprocess.Popen(
164
+ ("echo", sudo_password), stdout=subprocess.PIPE
165
+ )
166
+ s = subprocess.run(
167
+ [
168
+ "sudo",
169
+ "-S",
170
+ memdump_sh_path,
171
+ str(viber_pid),
172
+ ],
173
+ capture_output=True,
174
+ stdin=sudo_password_pipe.stdout,
175
+ ).stdout
176
+
177
+ member_id_addr = s.find(b"X-Viber-Auth-Mid: ")
178
+ m_token_addr = s.find(b"X-Viber-Auth-Token: ")
179
+ m_ts_addr = s.find(b"X-Viber-Auth-Timestamp: ")
180
+
181
+ if member_id_addr == -1 or m_token_addr == -1 or m_ts_addr == -1:
182
+ return None, MSG_NO_AUTH
183
+
184
+ member_id_addr += 18
185
+ m_token_addr += 20
186
+ m_ts_addr += 24
187
+
188
+ member_id_bytes = s[member_id_addr : member_id_addr + 20]
189
+ member_id_term = member_id_bytes.find(b"\x0d\x0a")
190
+ if member_id_term == -1:
191
+ return None, MSG_NO_AUTH
192
+ member_id = member_id_bytes[:member_id_term].decode(encoding="ascii")
193
+
194
+ m_token = s[m_token_addr : m_token_addr + 64].decode(encoding="ascii")
195
+ m_ts = s[m_ts_addr : m_ts_addr + 13].decode(encoding="ascii")
196
+
197
+ killall("viber")
198
+
199
+ viber_auth = f"member_id:{member_id};m_token:{m_token};m_ts:{m_ts}"
200
+ msg = "Got viber_auth successfully:\n"
201
+ msg += f"{viber_auth=}\n"
202
+
203
+ return viber_auth, msg
204
+
205
+ def get_auth_darwin(self, viber_bin_path: str) -> Tuple[Optional[str], str]:
206
+ member_id = None
207
+ m_token = None
208
+ m_ts = None
209
+
210
+ csrutil_status = subprocess.run(
211
+ ["csrutil", "status"], capture_output=True, text=True
212
+ ).stdout
213
+
214
+ if "enabled" in csrutil_status:
215
+ return None, MSG_SIP_ENABLED
216
+
217
+ killed = killall("viber")
218
+ if killed:
219
+ time.sleep(5)
220
+ subprocess.run(
221
+ ["open", "-n", viber_bin_path],
222
+ stdout=subprocess.DEVNULL,
223
+ stderr=subprocess.DEVNULL,
224
+ )
225
+ time.sleep(10)
226
+
227
+ viber_pid = subprocess.run(
228
+ ["pgrep", "Viber"], capture_output=True, text=True
229
+ ).stdout.strip()
230
+ subprocess.run(
231
+ [
232
+ "lldb",
233
+ "--attach-pid",
234
+ viber_pid,
235
+ "-o",
236
+ "process save-core /tmp/viber.dmp",
237
+ "-o",
238
+ "quit",
239
+ ],
240
+ stdout=subprocess.DEVNULL,
241
+ stderr=subprocess.DEVNULL,
242
+ )
243
+
244
+ with open("/tmp/viber.dmp", "rb") as f:
245
+ s = f.read()
246
+
247
+ os.remove("/tmp/viber.dmp")
248
+ killall("viber")
249
+
250
+ member_id_addr = s.find(b"X-Viber-Auth-Mid: ")
251
+ m_token_addr = s.find(b"X-Viber-Auth-Token: ")
252
+ m_ts_addr = s.find(b"X-Viber-Auth-Timestamp: ")
253
+
254
+ if member_id_addr == -1 or m_token_addr == -1 or m_ts_addr == -1:
255
+ return None, MSG_NO_AUTH
256
+
257
+ member_id_addr += 18
258
+ m_token_addr += 20
259
+ m_ts_addr += 24
260
+
261
+ member_id_bytes = s[member_id_addr : member_id_addr + 20]
262
+ member_id_term = member_id_bytes.find(b"\x0d\x0a")
263
+ if member_id_term == -1:
264
+ return None, MSG_NO_AUTH
265
+ member_id = member_id_bytes[:member_id_term].decode(encoding="ascii")
266
+
267
+ m_token = s[m_token_addr : m_token_addr + 64].decode(encoding="ascii")
268
+ m_ts = s[m_ts_addr : m_ts_addr + 13].decode(encoding="ascii")
269
+
270
+ viber_auth = f"member_id:{member_id};m_token:{m_token};m_ts:{m_ts}"
271
+ msg = "Got viber_auth successfully:\n"
272
+ msg += f"{viber_auth=}\n"
273
+
274
+ return viber_auth, msg
275
+
276
+ def get_viber_desktop(self) -> Optional[str]:
277
+ if platform.system() == "Windows":
278
+ viber_bin_path = os.path.expandvars("%localappdata%/Viber/Viber.exe")
279
+ elif platform.system() == "Darwin":
280
+ viber_bin_path = "/Applications/Viber.app"
281
+ else:
282
+ if os.path.isfile("/opt/viber/Viber"):
283
+ viber_bin_path = "/opt/viber/Viber"
284
+ else:
285
+ viber_which = shutil.which("Viber")
286
+ if viber_which is None:
287
+ viber_which = shutil.which("viber")
288
+ if viber_which is None:
289
+ viber_which = shutil.which("viber.AppImage")
290
+ if viber_which is None:
291
+ viber_bin_path = "viber"
292
+ else:
293
+ viber_bin_path = viber_which
294
+
295
+ if Path(viber_bin_path).is_file() or Path(viber_bin_path).is_dir():
296
+ return viber_bin_path
297
+
298
+ return None
299
+
300
+ def get_cred(
301
+ self,
302
+ viber_bin_path: Optional[str] = None,
303
+ ) -> Tuple[Optional[str], str]:
304
+ if not viber_bin_path:
305
+ viber_bin_path = self.get_viber_desktop()
306
+
307
+ if not viber_bin_path:
308
+ return None, MSG_NO_BIN
309
+
310
+ if platform.system() == "Windows":
311
+ return self.get_auth_windows(viber_bin_path)
312
+ elif platform.system() == "Darwin":
313
+ return self.get_auth_darwin(viber_bin_path)
314
+ else:
315
+ return self.get_auth_linux(viber_bin_path)
@@ -37,7 +37,7 @@ RELATED_NAME = (
37
37
  )
38
38
 
39
39
  BLACKLIST_PREFIX = ("cover",)
40
- BLACKLIST_SUFFIX = (".txt", ".m4a", ".wastickers", ".DS_Store", "._.DS_Store")
40
+ BLACKLIST_SUFFIX = (".txt", ".m4a", ".wastickers", ".zip", ".DS_Store", "._.DS_Store")
41
41
 
42
42
  XCODE_IMESSAGE_ICONSET = {
43
43
  "App-Store-1024x1024pt.png": (1024, 1024),
@@ -124,20 +124,16 @@ class FormatVerify:
124
124
  else:
125
125
  file_animated = CodecInfo.is_anim(file)
126
126
 
127
- if (
128
- file_animated is True
129
- and size
130
- and size[1] is not None
131
- and file_size > size[1]
132
- ):
133
- return False
134
- if (
135
- file_animated is False
136
- and size
137
- and size[0] is not None
138
- and file_size > size[0]
139
- ):
140
- return False
127
+ if file_animated is True:
128
+ if not size[1]:
129
+ return True
130
+ elif file_size > size[1]:
131
+ return False
132
+ else:
133
+ if not size[0]:
134
+ return True
135
+ elif file_size > size[0]:
136
+ return False
141
137
 
142
138
  return True
143
139
 
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
- __version__ = "2.8.13"
3
+ __version__ = "2.9.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.8.13
3
+ Version: 2.9.0
4
4
  Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, Viber, iMessage. Written in Python.
5
5
  Author-email: laggykiller <chaudominic2@gmail.com>
6
6
  Maintainer-email: laggykiller <chaudominic2@gmail.com>
@@ -371,13 +371,14 @@ Requires-Dist: av ~=12.1.0
371
371
  Requires-Dist: beautifulsoup4 ~=4.12.3
372
372
  Requires-Dist: rookiepy ~=0.5.1
373
373
  Requires-Dist: imagequant ~=1.1.1
374
- Requires-Dist: js2py ~=0.74
375
374
  Requires-Dist: memory-tempfile ~=2.2.3
376
375
  Requires-Dist: mergedeep ~=1.3.4
377
376
  Requires-Dist: numpy >=1.22.4
378
377
  Requires-Dist: Pillow ~=10.3.0
379
378
  Requires-Dist: pyoxipng ~=9.0.0
380
379
  Requires-Dist: python-telegram-bot ~=21.2
380
+ Requires-Dist: psutil ~=5.9.8
381
+ Requires-Dist: PyMemoryEditor ~=1.5.22
381
382
  Requires-Dist: requests ~=2.32.3
382
383
  Requires-Dist: rlottie-python ~=1.3.5
383
384
  Requires-Dist: signalstickers-client-fork-laggykiller ~=3.3.0.post2
@@ -483,24 +484,27 @@ usage: sticker-convert.py [-h] [--version] [--no-confirm] [--no-progress] [--cus
483
484
  [--input-dir INPUT_DIR]
484
485
  [--download-auto DOWNLOAD_AUTO | --download-signal DOWNLOAD_SIGNAL | --download-telegram DOWNLOAD_TELEGRAM | --download-line DOWNLOAD_LINE | --download-kakao DOWNLOAD_KAKAO | --download-viber DOWNLOAD_VIBER]
485
486
  [--output-dir OUTPUT_DIR] [--author AUTHOR] [--title TITLE]
486
- [--export-signal | --export-telegram | --export-telegram-emoji | --export-whatsapp | --export-imessage]
487
+ [--export-signal | --export-telegram | --export-telegram-emoji | --export-whatsapp | --export-viber | --export-imessage]
487
488
  [--no-compress]
488
489
  [--preset {auto,signal,telegram,telegram_emoji,whatsapp,line,kakao,viber,imessage_small,imessage_medium,imessage_large,custom}]
489
490
  [--steps STEPS] [--processes PROCESSES] [--fps-min FPS_MIN] [--fps-max FPS_MAX]
490
491
  [--fps-power FPS_POWER] [--res-min RES_MIN] [--res-max RES_MAX] [--res-w-min RES_W_MIN]
491
- [--res-w-max RES_W_MAX] [--res-h-min RES_H_MIN] [--res-h-max RES_H_MAX] [--res-power RES_POWER]
492
- [--quality-min QUALITY_MIN] [--quality-max QUALITY_MAX] [--quality-power QUALITY_POWER]
493
- [--color-min COLOR_MIN] [--color-max COLOR_MAX] [--color-power COLOR_POWER]
494
- [--duration-min DURATION_MIN] [--duration-max DURATION_MAX] [--padding-percent PADDING_PERCENT]
495
- [--bg-color BG_COLOR] [--vid-size-max VID_SIZE_MAX] [--img-size-max IMG_SIZE_MAX]
496
- [--vid-format VID_FORMAT] [--img-format IMG_FORMAT] [--fake-vid] [--scale-filter SCALE_FILTER]
497
- [--quantize-method QUANTIZE_METHOD] [--cache-dir CACHE_DIR] [--default-emoji DEFAULT_EMOJI]
498
- [--signal-uuid SIGNAL_UUID] [--signal-password SIGNAL_PASSWORD] [--signal-get-auth]
492
+ [--res-w-max RES_W_MAX] [--res-h-min RES_H_MIN] [--res-h-max RES_H_MAX]
493
+ [--res-power RES_POWER] [--quality-min QUALITY_MIN] [--quality-max QUALITY_MAX]
494
+ [--quality-power QUALITY_POWER] [--color-min COLOR_MIN] [--color-max COLOR_MAX]
495
+ [--color-power COLOR_POWER] [--duration-min DURATION_MIN] [--duration-max DURATION_MAX]
496
+ [--padding-percent PADDING_PERCENT] [--bg-color BG_COLOR] [--vid-size-max VID_SIZE_MAX]
497
+ [--img-size-max IMG_SIZE_MAX] [--vid-format VID_FORMAT] [--img-format IMG_FORMAT]
498
+ [--fake-vid] [--scale-filter SCALE_FILTER] [--quantize-method QUANTIZE_METHOD]
499
+ [--cache-dir CACHE_DIR] [--default-emoji DEFAULT_EMOJI] [--signal-uuid SIGNAL_UUID]
500
+ [--signal-password SIGNAL_PASSWORD] [--signal-get-auth]
499
501
  [--signal-data-dir SIGNAL_DATA_DIR] [--telegram-token TELEGRAM_TOKEN]
500
- [--telegram-userid TELEGRAM_USERID] [--kakao-auth-token KAKAO_AUTH_TOKEN] [--kakao-get-auth]
501
- [--kakao-username KAKAO_USERNAME] [--kakao-password KAKAO_PASSWORD]
502
+ [--telegram-userid TELEGRAM_USERID] [--kakao-auth-token KAKAO_AUTH_TOKEN]
503
+ [--kakao-get-auth] [--kakao-username KAKAO_USERNAME] [--kakao-password KAKAO_PASSWORD]
502
504
  [--kakao-country-code KAKAO_COUNTRY_CODE] [--kakao-phone-number KAKAO_PHONE_NUMBER]
503
- [--line-get-auth] [--line-cookies LINE_COOKIES] [--save-cred SAVE_CRED]
505
+ [--line-get-auth] [--line-cookies LINE_COOKIES] [--viber-auth VIBER_AUTH]
506
+ [--viber-get-auth VIBER_GET_AUTH] [--viber-bin-path VIBER_BIN_PATH]
507
+ [--save-cred SAVE_CRED]
504
508
 
505
509
  CLI for stickers-convert
506
510
 
@@ -550,6 +554,7 @@ Output options:
550
554
  --export-telegram-emoji
551
555
  Upload to Telegram (Custom emoji)
552
556
  --export-whatsapp Create a .wastickers file for uploading to WhatsApp
557
+ --export-viber Upload to Viber
553
558
  --export-imessage Create Xcode project for importing to iMessage
554
559
 
555
560
  Compression options:
@@ -668,6 +673,14 @@ Credentials options:
668
673
  --line-get-auth Get Line cookies from browser, which is required to create custom message stickers.
669
674
  --line-cookies LINE_COOKIES
670
675
  Set Line cookies, which is required to create custom message stickers.
676
+ --viber-auth VIBER_AUTH
677
+ Set Viber authentication data.
678
+ Required for uploading Viber stickers.
679
+ --viber-get-auth VIBER_GET_AUTH
680
+ Generate Viber authentication data.
681
+ --viber-bin-path VIBER_BIN_PATH
682
+ Specify location of Viber Desktop application.
683
+ Useful for portable installation.
671
684
  --save-cred SAVE_CRED
672
685
  Save Signal and Telegram credentials.
673
686
  ```
@@ -840,5 +853,5 @@ See [docs/TODO.md](docs/TODO.md)
840
853
  - Banner generated from [GitHub Socialify](https://socialify.git.ci/)
841
854
 
842
855
  ## DISCLAIMER
843
- - The author of this repo is NOT affiliated with Signal, Telegram, WhatsApp, Line, Kakao or Sticker Maker.
856
+ - The author of this repo is NOT affiliated with Signal, Telegram, WhatsApp, Line, Kakao, Viber, iMessage or Sticker Maker.
844
857
  - The author of this repo is NOT repsonsible for any legal consequences and loss incurred from using this repo.
@@ -1,15 +1,15 @@
1
1
  sticker_convert/__init__.py,sha256=iQnv6UOOA69c3soAn7ZOnAIubTIQSUxtq1Uhh8xRWvU,102
2
2
  sticker_convert/__main__.py,sha256=6RJauR-SCSSTT3TU7FFB6B6PVwsCxO2xZXtmZ3jc2Is,463
3
- sticker_convert/cli.py,sha256=DUPaI0Vw-a63TxxC2SSskLd1PlAuQtFOklggMo04IJc,18854
3
+ sticker_convert/cli.py,sha256=GO_rBmOAslgf-SHcvLjUE6rHzpBVfGi389RxuJZSkEU,19438
4
4
  sticker_convert/converter.py,sha256=XMiYzIzlcdvx_AFyyk7j-Zdyj3ablLFJFUZ6tjrlGIs,35861
5
5
  sticker_convert/definitions.py,sha256=ZhP2ALCEud-w9ZZD4c3TDG9eHGPZyaAL7zPUsJAbjtE,2073
6
- sticker_convert/gui.py,sha256=TRPGwMhSMPHnZppHmw2OWHKTJtGoeLpGWD0eRYi4_yk,30707
7
- sticker_convert/job.py,sha256=vKv1--y4MVmZV_IBpUhEfNEiUeEqrTR1umzlALPXKdw,25775
8
- sticker_convert/job_option.py,sha256=JHAFCxp7-dDwD-1PbpYLAFRF3OoJu8cj_BjOm5r8Gp8,7732
9
- sticker_convert/version.py,sha256=9-pwqpZSBU0RJFweDIiL0yO5EXYfWSFjeU-Fw26RIA4,47
6
+ sticker_convert/gui.py,sha256=hZOp2SyEYKbCRm9SRTItBqEk724SHtSqK_Txo0wpL8Q,31194
7
+ sticker_convert/job.py,sha256=4C2WwB3PFldacqI8UPnM10thM087VLEl9wn6P9_LtS0,26128
8
+ sticker_convert/job_option.py,sha256=yFwHEhW8Gzp9dfiXakkCREfejAIJhiOxwD4Wlg9jcPk,7805
9
+ sticker_convert/version.py,sha256=UUJ5qrYrmZsock_EC-nYp5wKxs3ZAkgVkQPLxSv6l1E,46
10
10
  sticker_convert/downloaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  sticker_convert/downloaders/download_base.py,sha256=x18bI2mPpbXRnSmStBHEb1IvN-VPCilOHLQUs6YPUEU,4041
12
- sticker_convert/downloaders/download_kakao.py,sha256=d0950G_Nqpb9cCWgVKVJBtSNFSykv5zrye0uqHAGenY,14193
12
+ sticker_convert/downloaders/download_kakao.py,sha256=TCygK-LiSkk3yEYZymZsHVwtW5JmQX6JeIneh25XxFA,14984
13
13
  sticker_convert/downloaders/download_line.py,sha256=9WzOWujTbZdAqBi52k21OUEfRmcV1loCaJiDmg6dklw,17853
14
14
  sticker_convert/downloaders/download_signal.py,sha256=PfwscdbcEd_5C3Ecs0F8Qc8si1sLzLodAdnsHVwXgac,3063
15
15
  sticker_convert/downloaders/download_telegram.py,sha256=jufMqc78aXOPDr7fQf9ykkNyhQ7KVCp4gRBxs09NgMo,4614
@@ -20,7 +20,7 @@ sticker_convert/gui_components/frames/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCe
20
20
  sticker_convert/gui_components/frames/comp_frame.py,sha256=9k_UntKKi2G_g0byzoj1rdTqOq7q9mcnXiy799bYnr0,7257
21
21
  sticker_convert/gui_components/frames/config_frame.py,sha256=b3X4QAnGpde0OhthXHmjSyU_Yb5tYRUFXmy04Yi8Zmo,4316
22
22
  sticker_convert/gui_components/frames/control_frame.py,sha256=_XiOJ9JPUfiysDghGG04sEVLrXG9TMVlDZ60W0LhYVI,835
23
- sticker_convert/gui_components/frames/cred_frame.py,sha256=I3XrOv7kUOsvFWquuzWWpZWbLclqKQXgD7dx5pcTuY4,6499
23
+ sticker_convert/gui_components/frames/cred_frame.py,sha256=QCAmDfSgL-ykGxPsL_9kWFssbtVdrh17IWW28oxzdDg,7429
24
24
  sticker_convert/gui_components/frames/input_frame.py,sha256=5Vz1d6J1jkofvvzm43DxeIW_CjWfxa2QPYFnkAAiAfM,5040
25
25
  sticker_convert/gui_components/frames/output_frame.py,sha256=n2WLk22h61DoZli8WbFhd-h2CqWAebDXnBa051JBuOc,4260
26
26
  sticker_convert/gui_components/frames/progress_frame.py,sha256=LWUZg_iL7iiNTfu7N5Ct_pklZdghxihENi7DP9YozOE,4915
@@ -31,6 +31,7 @@ sticker_convert/gui_components/windows/base_window.py,sha256=xBE1peGMPvWsdrFej0C
31
31
  sticker_convert/gui_components/windows/kakao_get_auth_window.py,sha256=AvXB2Q8pAPkKILHTvlLGV9jfBcvskCA4arko4nvBTdo,7115
32
32
  sticker_convert/gui_components/windows/line_get_auth_window.py,sha256=S4ES_lk2-GDvPokZtYALnUc5zW1VbS4WulNqO9K1aSs,3375
33
33
  sticker_convert/gui_components/windows/signal_get_auth_window.py,sha256=kbJPe558lLP4PbPT2mCw4Xgh06FX5mBEZXoW-Q1LvWY,4584
34
+ sticker_convert/gui_components/windows/viber_get_auth_window.py,sha256=_LOAhyNEp4OL24i_PsVtXYE01EArH-9gOOdEaFG4H30,4876
34
35
  sticker_convert/ios-message-stickers-template/.gitignore,sha256=4uuTph_9eHfqXHUavLOmGOji6aIHOif2bUEU_hCBn4Y,9
35
36
  sticker_convert/ios-message-stickers-template/README.md,sha256=oN0FvJkCWWjSZ3PMrCvY3T1zCsdkZYFgGHAoFh0Kmt8,467
36
37
  sticker_convert/ios-message-stickers-template/.github/FUNDING.yml,sha256=3LlmdSAGDsBA2o_C1iBYTNLwkABnyZuN0zxgPPyd-f8,70
@@ -67,35 +68,38 @@ sticker_convert/resources/NotoColorEmoji.ttf,sha256=LurIVaCIA8bSCfjrdO1feYr0bhKL
67
68
  sticker_convert/resources/appicon.icns,sha256=FB2DVTOQcFfQNZ9RcyG3z9c9k7eOiI1qw0IJhXMRFg4,5404
68
69
  sticker_convert/resources/appicon.ico,sha256=-ldugcl2Yq2pBRTktnhGKWInpKyWzRjCiPvMr3XPTlc,38078
69
70
  sticker_convert/resources/appicon.png,sha256=6XBEQz7PnerqS43aRkwpWolFG4WvKMuQ-st1ly-_JPg,5265
70
- sticker_convert/resources/compression.json,sha256=8SAv5m7_R2QFaU656W7gpliCJF9ZmGdE_XfnJU3D0ZE,12156
71
+ sticker_convert/resources/compression.json,sha256=tNBGCmFqZ4Bsik1-xtvkOSlRu1uF6KdkggNTUtjWTYU,12156
71
72
  sticker_convert/resources/emoji.json,sha256=sXSuKusyG1L2Stuf9BL5ZqfzOIOdeAeE3RXcrXAsLdY,413367
72
- sticker_convert/resources/help.json,sha256=9A7zXYrHMkIE75MhDD3xoFuk9jofFRGCVVXH_g_h9bk,6634
73
+ sticker_convert/resources/help.json,sha256=VgRYw5iNQGn_CDA4pTnk5QUO21lsx0JIvWgUV2kHPvY,6906
73
74
  sticker_convert/resources/input.json,sha256=S3CkInBMLrk5OS9aJfuTCDsf_64NOjNT3IKQr7d1hM0,2665
74
- sticker_convert/resources/output.json,sha256=QYP2gqDvEaAm5I9bH4NReaB1XMLboevv69u-V8YdZUs,1373
75
+ sticker_convert/resources/memdump.sh,sha256=YbdX5C5RyCnoeDUE6JgTo8nQXKhrUw5-kFDx5bQp9tY,651
76
+ sticker_convert/resources/output.json,sha256=V4OseXEm3O16cAjHDVZRq8-SY-0_7cFFR_cyF-0Y_eQ,1570
75
77
  sticker_convert/uploaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
78
  sticker_convert/uploaders/compress_wastickers.py,sha256=SMPf1_ir30ZKO2ChHspDFuyaufx0XeVBVLOlHmawEdY,6021
77
79
  sticker_convert/uploaders/upload_base.py,sha256=uQupPn6r4zrlAzpKzzX7CgvZb69ATyrwPKahWOQj0ds,1203
78
80
  sticker_convert/uploaders/upload_signal.py,sha256=eZNfTwnZzPmJcl_UCfJT6rrmLlNpD2EKfxrO2jdi1yg,6396
79
81
  sticker_convert/uploaders/upload_telegram.py,sha256=XnspO9VVbKND0gybUwdFTSzDBVDxLw9O_R7chnVQ0t0,15695
82
+ sticker_convert/uploaders/upload_viber.py,sha256=DiY54RstBtVJEfp6rGo0cpABx0X2qI873pJ6tTH-Q9U,6189
80
83
  sticker_convert/uploaders/xcode_imessage.py,sha256=1gvOljf6kYsq_11tYhnF19Yf4oGY5y34te2DWBRMwf0,11254
81
84
  sticker_convert/utils/callback.py,sha256=spYUGlklOs1yPZAxoqwOWgR1sdimpfM8a27if3TaVYk,6155
82
85
  sticker_convert/utils/url_detect.py,sha256=L2QwE2jwN85MoyYsW_4GvBHuoedrlhoIdAmzwrmaKLs,840
83
86
  sticker_convert/utils/auth/get_kakao_auth.py,sha256=ipAZ1DUd5CMTpUoxRXHVOFC3DKIpxwxpTYAfrOJ6UZ8,9829
84
87
  sticker_convert/utils/auth/get_line_auth.py,sha256=8l8ha2vQmk3rHGvDE7PkcxQXbH3oe62LKbI3qVUtvqc,2196
85
88
  sticker_convert/utils/auth/get_signal_auth.py,sha256=6Sx-lMuyBHeX1RpjAWI8u03qnRu9fmO4p89pd7fowOE,4925
89
+ sticker_convert/utils/auth/get_viber_auth.py,sha256=U3_8qxVifiZ7T47PMW6Cdo7CcLJnUW-_rf8QIYL9bYY,9984
86
90
  sticker_convert/utils/files/cache_store.py,sha256=etfe614OAhAyrnM5fGeESKq6R88YLNqkqkxSzEmZ0V0,1047
87
91
  sticker_convert/utils/files/json_manager.py,sha256=Vr6pZJdLMkrJJWN99210aduVHb0ILyf0SSTaw4TZqgc,541
88
92
  sticker_convert/utils/files/json_resources_loader.py,sha256=flZFixUXRTrOAhvRQpuSQgmJ69yXL94sxukcowLT1JQ,1049
89
- sticker_convert/utils/files/metadata_handler.py,sha256=UVKpwflsXwiVh-F-HNr0UcrixebfKQTU44iaPUhz-qw,10100
93
+ sticker_convert/utils/files/metadata_handler.py,sha256=KDwzCwSckTob2VacOvzLdu1256WLicmzXgkhfFvRBzo,10108
90
94
  sticker_convert/utils/files/run_bin.py,sha256=QalA9je6liHxiOtxsjsFsIkc2t59quhcJCVpP1X3p50,1743
91
95
  sticker_convert/utils/files/sanitize_filename.py,sha256=HBklPGsHRJjFQUIC5rYTQsUrsuTtezZXIEA8CPhLP8A,2156
92
96
  sticker_convert/utils/media/apple_png_normalize.py,sha256=LbrQhc7LlYX4I9ek4XJsZE4l0MygBA1jB-PFiYLEkzk,3657
93
97
  sticker_convert/utils/media/codec_info.py,sha256=1QfW3wgZ5vOk7T4XtLHYvJK1x8RbASRPSvhKEPkcu9A,15747
94
98
  sticker_convert/utils/media/decrypt_kakao.py,sha256=4wq9ZDRnFkx1WmFZnyEogBofiLGsWQM_X69HlA36578,1947
95
- sticker_convert/utils/media/format_verify.py,sha256=Xf94jyqk_6M9IlFGMy0wYIgQKn_yg00nD4XW0CgAbew,5732
96
- sticker_convert-2.8.13.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
97
- sticker_convert-2.8.13.dist-info/METADATA,sha256=7GSocwPMQW299PlQZ9BHiA5LGu-Je1_UfMyh3uBbZ-Q,50404
98
- sticker_convert-2.8.13.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
99
- sticker_convert-2.8.13.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
100
- sticker_convert-2.8.13.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
101
- sticker_convert-2.8.13.dist-info/RECORD,,
99
+ sticker_convert/utils/media/format_verify.py,sha256=MH68GLJfXeL8WFT8emtj355K5BLAtUX64tQ59nugx2c,5673
100
+ sticker_convert-2.9.0.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
101
+ sticker_convert-2.9.0.dist-info/METADATA,sha256=aGTUdCCINVKxrj8kM3b5pMpMDKbVu51_uuvVR8ee_2A,51091
102
+ sticker_convert-2.9.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
103
+ sticker_convert-2.9.0.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
104
+ sticker_convert-2.9.0.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
105
+ sticker_convert-2.9.0.dist-info/RECORD,,