sticker-convert 2.8.14__py3-none-any.whl → 2.9.1__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())
@@ -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:
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,149 @@
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
+ else:
55
+ self.explanation_lbl2 = Label(
56
+ self.frame_info,
57
+ text="You may be asked for admin password.",
58
+ justify="left",
59
+ anchor="w",
60
+ )
61
+
62
+ self.explanation_lbl0.grid(column=0, row=0, sticky="w", padx=3, pady=3)
63
+ self.explanation_lbl1.grid(column=0, row=1, sticky="w", padx=3, pady=3)
64
+ self.explanation_lbl2.grid(column=0, row=2, sticky="w", padx=3, pady=3)
65
+
66
+ # Start button frame
67
+ self.launch_btn = Button(
68
+ self.frame_btns,
69
+ text="Launch Viber Desktop",
70
+ command=self.cb_launch_viber,
71
+ bootstyle="secondary", # type: ignore
72
+ )
73
+
74
+ self.get_cred_btn = Button(
75
+ self.frame_btns,
76
+ text="Get auth data",
77
+ command=self.cb_get_cred,
78
+ bootstyle="default", # type: ignore
79
+ )
80
+
81
+ self.launch_btn.pack()
82
+ self.get_cred_btn.pack()
83
+
84
+ # Config frame
85
+ self.setdir_lbl = Label(
86
+ self.frame_config,
87
+ text=self.gui.help["cred"]["viber_bin_path"],
88
+ justify="left",
89
+ anchor="w",
90
+ )
91
+
92
+ self.setdir_entry = Entry(
93
+ self.frame_config,
94
+ textvariable=self.gui.viber_bin_path_var,
95
+ width=32,
96
+ )
97
+ self.setdir_btn = Button(
98
+ self.frame_config,
99
+ text="Choose",
100
+ command=self.cb_setdir,
101
+ width=8,
102
+ bootstyle="secondary", # type: ignore
103
+ )
104
+
105
+ self.setdir_lbl.grid(column=0, row=0, columnspan=2, sticky="w", padx=3, pady=3)
106
+ self.setdir_entry.grid(column=0, row=1, sticky="w", padx=3, pady=3)
107
+ self.setdir_btn.grid(column=1, row=1, sticky="e", padx=3, pady=3)
108
+
109
+ GUIUtils.finalize_window(self)
110
+
111
+ def cb_get_cred(self) -> None:
112
+ m = GetViberAuth(self.cb_ask_str_viber)
113
+
114
+ viber_bin_path = None
115
+ if self.gui.viber_bin_path_var.get():
116
+ viber_bin_path = self.gui.viber_bin_path_var.get()
117
+
118
+ viber_auth, msg = m.get_cred(viber_bin_path)
119
+
120
+ if viber_auth:
121
+ if not self.gui.creds.get("viber"):
122
+ self.gui.creds["viber"] = {}
123
+ self.gui.creds["viber"]["auth"] = viber_auth
124
+ self.gui.viber_auth_var.set(viber_auth)
125
+
126
+ self.gui.save_creds()
127
+ self.gui.highlight_fields()
128
+
129
+ self.cb_msg_block_viber(msg)
130
+
131
+ def cb_launch_viber(self) -> None:
132
+ m = GetViberAuth(self.cb_ask_str_viber)
133
+ viber_bin_path = m.get_viber_desktop()
134
+
135
+ if self.gui.viber_auth_var.get():
136
+ viber_bin_path = self.gui.viber_auth_var.get()
137
+
138
+ if viber_bin_path:
139
+ Popen([viber_bin_path])
140
+ else:
141
+ self.cb_msg_block_viber("Error: Viber Desktop not installed.")
142
+
143
+ def cb_setdir(self) -> None:
144
+ orig_input_dir = self.gui.viber_bin_path_var.get()
145
+ if not Path(orig_input_dir).is_dir():
146
+ orig_input_dir = ""
147
+ input_dir = filedialog.askdirectory(initialdir=orig_input_dir)
148
+ if input_dir:
149
+ 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
@@ -0,0 +1,8 @@
1
+ param($processId)
2
+ $dumpFilePath = "$Env:TEMP\memdump.bin.$processId"
3
+
4
+ Powershell -c rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump $processId $dumpFilePath full
5
+
6
+ icacls $dumpFilePath /remove "Everyone"
7
+ icacls $dumpFilePath /grant "Everyone:(r)"
8
+ icacls $dumpFilePath /grant "Everyone:(w)"
@@ -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,441 @@
1
+ #!/usr/bin/env python3
2
+ import importlib.util
3
+ import os
4
+ import platform
5
+ import shutil
6
+ import signal
7
+ import subprocess
8
+ import time
9
+ from getpass import getpass
10
+ from pathlib import Path
11
+ from typing import Callable, List, Optional, Tuple, cast
12
+
13
+ from sticker_convert.definitions import ROOT_DIR
14
+
15
+ MSG_NO_BIN = """Viber Desktop not detected.
16
+ Download and install Viber Desktop,
17
+ then login to Viber Desktop and try again."""
18
+ MSG_NO_AUTH = """Viber Desktop installed,
19
+ but viber_auth not found.
20
+ Please login to Viber Desktop and try again."""
21
+ MSG_SIP_ENABLED = """You need to disable SIP:
22
+ 1. Restart computer in Recovery mode
23
+ 2. Launch Terminal from the Utilities menu
24
+ 3. Run the command `csrutil disable`
25
+ 4. Restart your computer"""
26
+ MSG_NO_PGREP = "pgrep command or psutil python package is necessary"
27
+ MSG_LAUNCH_FAIL = "Failed to launch Viber"
28
+ MSG_PERMISSION_ERROR = "Failed to read Viber process memory"
29
+
30
+
31
+ def check_admin_windows() -> bool:
32
+ username = os.getenv("username")
33
+ if username is None:
34
+ return False
35
+
36
+ s = subprocess.run(
37
+ ["net", "user", username],
38
+ capture_output=True,
39
+ text=True,
40
+ ).stdout
41
+
42
+ return True if "*Administrators" in s else False
43
+
44
+
45
+ def check_admin_linux() -> bool:
46
+ s = subprocess.run(
47
+ ["sudo", "-l"],
48
+ capture_output=True,
49
+ text=True,
50
+ ).stdout
51
+
52
+ return True if "may run the following commands" in s else False
53
+
54
+
55
+ def killall(name: str) -> bool:
56
+ result = False
57
+
58
+ while True:
59
+ pid = find_pid_by_name(name)
60
+ if pid is not None:
61
+ os.kill(pid, signal.SIGTERM)
62
+ result = True
63
+ else:
64
+ break
65
+
66
+ return result
67
+
68
+
69
+ def find_pid_by_name(name: str) -> Optional[int]:
70
+ if platform.system() == "Windows":
71
+ s = subprocess.run(
72
+ ["powershell", "-c", "Get-Process", f"*{name}*"],
73
+ capture_output=True,
74
+ text=True,
75
+ ).stdout
76
+
77
+ for line in s.split("\n"):
78
+ if name in line.lower():
79
+ info = name.split()
80
+ pid = info[5]
81
+ if pid.isnumeric():
82
+ return int(pid)
83
+
84
+ return None
85
+ else:
86
+ if platform.system() == "Darwin":
87
+ pattern = "Viber"
88
+ else:
89
+ pattern = ".*[Vv]iber.*"
90
+ pid = (
91
+ subprocess.run(["pgrep", pattern], capture_output=True, text=True)
92
+ .stdout.split("\n")[0]
93
+ .strip()
94
+ )
95
+ if pid == "" or pid.isnumeric() is False:
96
+ return None
97
+ else:
98
+ return int(pid)
99
+
100
+
101
+ if importlib.util.find_spec("psutil"):
102
+ import psutil
103
+
104
+ def killall(name: str) -> bool:
105
+ result = False
106
+
107
+ for proc in psutil.process_iter(): # type: ignore
108
+ if name in proc.name().lower():
109
+ proc.kill()
110
+ result = True
111
+
112
+ return result
113
+
114
+ def find_pid_by_name(name: str) -> Optional[int]:
115
+ for proc in psutil.process_iter(): # type: ignore
116
+ if name in proc.name().lower():
117
+ return proc.pid
118
+
119
+ return None
120
+
121
+
122
+ class GetViberAuth:
123
+ def __init__(self, cb_ask_str: Callable[..., str] = input):
124
+ self.cb_ask_str = cb_ask_str
125
+
126
+ def relaunch_viber(self, viber_bin_path: str) -> Optional[int]:
127
+ killed = killall("viber")
128
+ if killed:
129
+ time.sleep(5)
130
+
131
+ if platform.system() == "Darwin":
132
+ cmd = ["open", "-n", viber_bin_path]
133
+ else:
134
+ cmd = [viber_bin_path]
135
+ subprocess.Popen(cmd)
136
+ time.sleep(10)
137
+
138
+ return find_pid_by_name("viber")
139
+
140
+ def get_mem_windows(self, viber_pid: int) -> Tuple[Optional[bytes], str]:
141
+ from pathlib import WindowsPath
142
+
143
+ memdump_ps_path = str(WindowsPath(ROOT_DIR / "resources/memdump_windows.ps1"))
144
+ arglist = (
145
+ f'-NoProfile -ExecutionPolicy Bypass -File "{memdump_ps_path}" {viber_pid}'
146
+ )
147
+ dump_fpath = os.path.expandvars(f"%temp%/memdump.bin.{viber_pid}")
148
+
149
+ cmd = [
150
+ "powershell",
151
+ "-NoProfile",
152
+ "-ExecutionPolicy",
153
+ "Bypass",
154
+ "-Command",
155
+ f"Start-Process -Verb RunAs powershell -ArgumentList '{arglist}'",
156
+ ]
157
+
158
+ subprocess.run(cmd, capture_output=True, text=True)
159
+
160
+ while True:
161
+ try:
162
+ with open(dump_fpath, "rb") as f:
163
+ s = f.read()
164
+ if len(s) != 0:
165
+ break
166
+ time.sleep(1)
167
+ except (FileNotFoundError, PermissionError):
168
+ pass
169
+
170
+ while True:
171
+ try:
172
+ os.remove(dump_fpath)
173
+ break
174
+ except PermissionError:
175
+ pass
176
+
177
+ return s, ""
178
+
179
+ def get_mem_linux(self, viber_pid: int) -> Tuple[Optional[bytes], str]:
180
+ memdump_sh_path = (ROOT_DIR / "resources/memdump_linux.sh").as_posix()
181
+
182
+ s = subprocess.run(
183
+ [
184
+ memdump_sh_path,
185
+ str(viber_pid),
186
+ ],
187
+ capture_output=True,
188
+ ).stdout
189
+
190
+ if len(s) > 1000:
191
+ pass
192
+ elif shutil.which("pkexec") and os.getenv("DISPLAY"):
193
+ s = subprocess.run(
194
+ [
195
+ "pkexec",
196
+ memdump_sh_path,
197
+ str(viber_pid),
198
+ ],
199
+ capture_output=True,
200
+ ).stdout
201
+ else:
202
+ prompt = "Enter sudo password: "
203
+ if self.cb_ask_str != input:
204
+ sudo_password = self.cb_ask_str(
205
+ prompt, initialvalue="", cli_show_initialvalue=False
206
+ )
207
+ else:
208
+ sudo_password = getpass(prompt)
209
+ sudo_password_pipe = subprocess.Popen(
210
+ ("echo", sudo_password), stdout=subprocess.PIPE
211
+ )
212
+ s = subprocess.run(
213
+ [
214
+ "sudo",
215
+ "-S",
216
+ memdump_sh_path,
217
+ str(viber_pid),
218
+ ],
219
+ capture_output=True,
220
+ stdin=sudo_password_pipe.stdout,
221
+ ).stdout
222
+
223
+ return s, ""
224
+
225
+ def get_mem_darwin(self, viber_pid: int) -> Tuple[Optional[bytes], str]:
226
+ subprocess.run(
227
+ [
228
+ "lldb",
229
+ "--attach-pid",
230
+ str(viber_pid),
231
+ "-o",
232
+ "process save-core /tmp/viber.dmp",
233
+ "-o",
234
+ "quit",
235
+ ],
236
+ stdout=subprocess.DEVNULL,
237
+ stderr=subprocess.DEVNULL,
238
+ )
239
+
240
+ with open("/tmp/viber.dmp", "rb") as f:
241
+ s = f.read()
242
+
243
+ os.remove("/tmp/viber.dmp")
244
+
245
+ return s, ""
246
+
247
+ def get_auth_by_pme(
248
+ self, viber_bin_path: str, relaunch: bool = True
249
+ ) -> Tuple[Optional[str], str]:
250
+ from PyMemoryEditor import OpenProcess # type: ignore
251
+
252
+ member_id = None
253
+ m_token = None
254
+ m_ts = None
255
+
256
+ if relaunch:
257
+ viber_pid = self.relaunch_viber(viber_bin_path)
258
+ else:
259
+ viber_pid = find_pid_by_name("viber")
260
+ if viber_pid is None:
261
+ return None, MSG_LAUNCH_FAIL
262
+
263
+ try:
264
+ with OpenProcess(pid=int(viber_pid)) as process:
265
+ for address in process.search_by_value(str, 18, "X-Viber-Auth-Mid: "): # type: ignore
266
+ member_id_addr = cast(int, address) + 18
267
+ member_id_bytes = process.read_process_memory(
268
+ member_id_addr, bytes, 20
269
+ )
270
+ member_id_term = member_id_bytes.find(b"\x0d\x0a")
271
+ if member_id_term == -1:
272
+ continue
273
+ member_id = member_id_bytes[:member_id_term].decode(
274
+ encoding="ascii"
275
+ )
276
+ break
277
+ if member_id is None:
278
+ return None, MSG_NO_AUTH
279
+
280
+ for address in process.search_by_value(str, 20, "X-Viber-Auth-Token: "): # type: ignore
281
+ m_token_addr = cast(int, address) + 20
282
+ m_token = process.read_process_memory(m_token_addr, str, 64)
283
+ break
284
+ if m_token is None:
285
+ return None, MSG_NO_AUTH
286
+
287
+ for address in process.search_by_value( # type: ignore
288
+ str, 24, "X-Viber-Auth-Timestamp: "
289
+ ):
290
+ m_ts_addr = cast(int, address) + 24
291
+ m_ts = process.read_process_memory(m_ts_addr, str, 13)
292
+ break
293
+ if m_ts is None:
294
+ return None, MSG_NO_AUTH
295
+ except PermissionError:
296
+ return None, MSG_PERMISSION_ERROR
297
+
298
+ viber_auth = f"member_id:{member_id};m_token:{m_token};m_ts:{m_ts}"
299
+ msg = "Got viber_auth successfully:\n"
300
+ msg += f"{viber_auth=}\n"
301
+
302
+ return viber_auth, msg
303
+
304
+ def get_auth_by_dump(
305
+ self, viber_bin_path: str, relaunch: bool = True
306
+ ) -> Tuple[Optional[str], str]:
307
+ member_id = None
308
+ m_token = None
309
+ m_ts = None
310
+
311
+ if platform.system() == "Darwin":
312
+ csrutil_status = subprocess.run(
313
+ ["csrutil", "status"], capture_output=True, text=True
314
+ ).stdout
315
+
316
+ if "enabled" in csrutil_status:
317
+ return None, MSG_SIP_ENABLED
318
+ elif (
319
+ platform.system() != "Windows"
320
+ and shutil.which("pgrep") is None
321
+ and importlib.find_loader("psutil") is None
322
+ ):
323
+ return None, MSG_NO_PGREP
324
+
325
+ if relaunch:
326
+ viber_pid = self.relaunch_viber(viber_bin_path)
327
+ else:
328
+ viber_pid = find_pid_by_name("viber")
329
+ if viber_pid is None:
330
+ return None, MSG_LAUNCH_FAIL
331
+
332
+ if platform.system() == "Windows":
333
+ s, msg = self.get_mem_windows(viber_pid)
334
+ elif platform.system() == "Darwin":
335
+ s, msg = self.get_mem_darwin(viber_pid)
336
+ else:
337
+ s, msg = self.get_mem_linux(viber_pid)
338
+
339
+ if s is None:
340
+ return None, msg
341
+
342
+ member_id_addr = s.find(b"X-Viber-Auth-Mid: ")
343
+ m_token_addr = s.find(b"X-Viber-Auth-Token: ")
344
+ m_ts_addr = s.find(b"X-Viber-Auth-Timestamp: ")
345
+
346
+ if member_id_addr == -1 or m_token_addr == -1 or m_ts_addr == -1:
347
+ return None, MSG_NO_AUTH
348
+
349
+ member_id_addr += 18
350
+ m_token_addr += 20
351
+ m_ts_addr += 24
352
+
353
+ member_id_bytes = s[member_id_addr : member_id_addr + 20]
354
+ member_id_term = member_id_bytes.find(b"\x0d\x0a")
355
+ if member_id_term == -1:
356
+ return None, MSG_NO_AUTH
357
+ member_id = member_id_bytes[:member_id_term].decode(encoding="ascii")
358
+
359
+ m_token = s[m_token_addr : m_token_addr + 64].decode(encoding="ascii")
360
+ m_ts = s[m_ts_addr : m_ts_addr + 13].decode(encoding="ascii")
361
+
362
+ viber_auth = f"member_id:{member_id};m_token:{m_token};m_ts:{m_ts}"
363
+ msg = "Got viber_auth successfully:\n"
364
+ msg += f"{viber_auth=}\n"
365
+
366
+ return viber_auth, msg
367
+
368
+ def get_viber_desktop(self) -> Optional[str]:
369
+ if platform.system() == "Windows":
370
+ viber_bin_path = os.path.expandvars("%localappdata%/Viber/Viber.exe")
371
+ elif platform.system() == "Darwin":
372
+ viber_bin_path = "/Applications/Viber.app"
373
+ else:
374
+ if os.path.isfile("/opt/viber/Viber"):
375
+ viber_bin_path = "/opt/viber/Viber"
376
+ else:
377
+ viber_which = shutil.which("Viber")
378
+ if viber_which is None:
379
+ viber_which = shutil.which("viber")
380
+ if viber_which is None:
381
+ viber_which = shutil.which("viber.AppImage")
382
+ if viber_which is None:
383
+ viber_bin_path = "viber"
384
+ else:
385
+ viber_bin_path = viber_which
386
+
387
+ if Path(viber_bin_path).is_file() or Path(viber_bin_path).is_dir():
388
+ return viber_bin_path
389
+
390
+ return None
391
+
392
+ def get_cred(
393
+ self,
394
+ viber_bin_path: Optional[str] = None,
395
+ ) -> Tuple[Optional[str], str]:
396
+ if not viber_bin_path:
397
+ viber_bin_path = self.get_viber_desktop()
398
+
399
+ if not viber_bin_path:
400
+ return None, MSG_NO_BIN
401
+
402
+ # get_auth_by_dump()
403
+ # + Fast
404
+ # - Requires admin
405
+
406
+ # get_auth_by_pme()
407
+ # + No admin (If have permission to read process)
408
+ # - Slow
409
+ # - Cannot run on macOS
410
+
411
+ # If admin, prefer get_auth_by_dump() over get_auth_by_pme(), vice versa
412
+ methods: List[Callable[[str, bool], Tuple[Optional[str], str]]] = []
413
+ relaunch = True
414
+ viber_auth = None
415
+ msg = ""
416
+
417
+ pme_present = importlib.util.find_spec("PyMemoryEditor") is not None
418
+ if platform.system() == "Darwin":
419
+ methods.append(self.get_auth_by_dump)
420
+ elif platform.system() == "Windows":
421
+ methods.append(self.get_auth_by_dump)
422
+ if pme_present:
423
+ methods.append(self.get_auth_by_pme)
424
+ if check_admin_windows() is False:
425
+ methods.reverse()
426
+ else:
427
+ if not os.path.isfile("/.dockerenv"):
428
+ methods.append(self.get_auth_by_dump)
429
+ if pme_present:
430
+ methods.append(self.get_auth_by_pme)
431
+ if check_admin_linux() is False:
432
+ methods.reverse()
433
+
434
+ for method in methods:
435
+ viber_auth, msg = method(viber_bin_path, relaunch)
436
+ relaunch = False
437
+ if viber_auth is not None:
438
+ break
439
+
440
+ killall("viber")
441
+ return viber_auth, msg
@@ -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.14"
3
+ __version__ = "2.9.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.8.14
3
+ Version: 2.9.1
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>
@@ -376,9 +376,11 @@ Requires-Dist: mergedeep ~=1.3.4
376
376
  Requires-Dist: numpy >=1.22.4
377
377
  Requires-Dist: Pillow ~=10.3.0
378
378
  Requires-Dist: pyoxipng ~=9.0.0
379
- Requires-Dist: python-telegram-bot ~=21.2
379
+ Requires-Dist: python-telegram-bot ~=21.3
380
+ Requires-Dist: psutil ~=5.9.8
381
+ Requires-Dist: PyMemoryEditor ~=1.5.22
380
382
  Requires-Dist: requests ~=2.32.3
381
- Requires-Dist: rlottie-python ~=1.3.5
383
+ Requires-Dist: rlottie-python ~=1.3.6
382
384
  Requires-Dist: signalstickers-client-fork-laggykiller ~=3.3.0.post2
383
385
  Requires-Dist: sqlcipher3-wheels ~=0.5.2.post1
384
386
  Requires-Dist: tqdm ~=4.66.4
@@ -482,24 +484,27 @@ usage: sticker-convert.py [-h] [--version] [--no-confirm] [--no-progress] [--cus
482
484
  [--input-dir INPUT_DIR]
483
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]
484
486
  [--output-dir OUTPUT_DIR] [--author AUTHOR] [--title TITLE]
485
- [--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]
486
488
  [--no-compress]
487
489
  [--preset {auto,signal,telegram,telegram_emoji,whatsapp,line,kakao,viber,imessage_small,imessage_medium,imessage_large,custom}]
488
490
  [--steps STEPS] [--processes PROCESSES] [--fps-min FPS_MIN] [--fps-max FPS_MAX]
489
491
  [--fps-power FPS_POWER] [--res-min RES_MIN] [--res-max RES_MAX] [--res-w-min RES_W_MIN]
490
- [--res-w-max RES_W_MAX] [--res-h-min RES_H_MIN] [--res-h-max RES_H_MAX] [--res-power RES_POWER]
491
- [--quality-min QUALITY_MIN] [--quality-max QUALITY_MAX] [--quality-power QUALITY_POWER]
492
- [--color-min COLOR_MIN] [--color-max COLOR_MAX] [--color-power COLOR_POWER]
493
- [--duration-min DURATION_MIN] [--duration-max DURATION_MAX] [--padding-percent PADDING_PERCENT]
494
- [--bg-color BG_COLOR] [--vid-size-max VID_SIZE_MAX] [--img-size-max IMG_SIZE_MAX]
495
- [--vid-format VID_FORMAT] [--img-format IMG_FORMAT] [--fake-vid] [--scale-filter SCALE_FILTER]
496
- [--quantize-method QUANTIZE_METHOD] [--cache-dir CACHE_DIR] [--default-emoji DEFAULT_EMOJI]
497
- [--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]
498
501
  [--signal-data-dir SIGNAL_DATA_DIR] [--telegram-token TELEGRAM_TOKEN]
499
- [--telegram-userid TELEGRAM_USERID] [--kakao-auth-token KAKAO_AUTH_TOKEN] [--kakao-get-auth]
500
- [--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]
501
504
  [--kakao-country-code KAKAO_COUNTRY_CODE] [--kakao-phone-number KAKAO_PHONE_NUMBER]
502
- [--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]
503
508
 
504
509
  CLI for stickers-convert
505
510
 
@@ -549,6 +554,7 @@ Output options:
549
554
  --export-telegram-emoji
550
555
  Upload to Telegram (Custom emoji)
551
556
  --export-whatsapp Create a .wastickers file for uploading to WhatsApp
557
+ --export-viber Upload to Viber
552
558
  --export-imessage Create Xcode project for importing to iMessage
553
559
 
554
560
  Compression options:
@@ -667,6 +673,14 @@ Credentials options:
667
673
  --line-get-auth Get Line cookies from browser, which is required to create custom message stickers.
668
674
  --line-cookies LINE_COOKIES
669
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.
670
684
  --save-cred SAVE_CRED
671
685
  Save Signal and Telegram credentials.
672
686
  ```
@@ -839,5 +853,5 @@ See [docs/TODO.md](docs/TODO.md)
839
853
  - Banner generated from [GitHub Socialify](https://socialify.git.ci/)
840
854
 
841
855
  ## DISCLAIMER
842
- - 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.
843
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=xfnmuNP-PsbPT9tAIe1hZe8BVTotwNbxoJXlFmvcuP4,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=baBhLdXSz6WrhsijOG00KYOzp3-KSIDIG59dfAQPMrQ,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=hHilDDzYaGU5BQmOwMF0NKnsysxh8loybfoFSNQQdSw,14955
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=Ne0DG4wog7Pzw-fPsbr7HX40okFFo1INusVCSwSAQdQ,5051
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,39 @@ 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_linux.sh,sha256=YbdX5C5RyCnoeDUE6JgTo8nQXKhrUw5-kFDx5bQp9tY,651
76
+ sticker_convert/resources/memdump_windows.ps1,sha256=CfyNSSEW3HJOkTu-mKrP3qh5aprN-1VCBfj-R1fELA0,302
77
+ sticker_convert/resources/output.json,sha256=V4OseXEm3O16cAjHDVZRq8-SY-0_7cFFR_cyF-0Y_eQ,1570
75
78
  sticker_convert/uploaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
79
  sticker_convert/uploaders/compress_wastickers.py,sha256=SMPf1_ir30ZKO2ChHspDFuyaufx0XeVBVLOlHmawEdY,6021
77
80
  sticker_convert/uploaders/upload_base.py,sha256=uQupPn6r4zrlAzpKzzX7CgvZb69ATyrwPKahWOQj0ds,1203
78
81
  sticker_convert/uploaders/upload_signal.py,sha256=eZNfTwnZzPmJcl_UCfJT6rrmLlNpD2EKfxrO2jdi1yg,6396
79
82
  sticker_convert/uploaders/upload_telegram.py,sha256=XnspO9VVbKND0gybUwdFTSzDBVDxLw9O_R7chnVQ0t0,15695
83
+ sticker_convert/uploaders/upload_viber.py,sha256=DiY54RstBtVJEfp6rGo0cpABx0X2qI873pJ6tTH-Q9U,6189
80
84
  sticker_convert/uploaders/xcode_imessage.py,sha256=1gvOljf6kYsq_11tYhnF19Yf4oGY5y34te2DWBRMwf0,11254
81
85
  sticker_convert/utils/callback.py,sha256=spYUGlklOs1yPZAxoqwOWgR1sdimpfM8a27if3TaVYk,6155
82
86
  sticker_convert/utils/url_detect.py,sha256=L2QwE2jwN85MoyYsW_4GvBHuoedrlhoIdAmzwrmaKLs,840
83
87
  sticker_convert/utils/auth/get_kakao_auth.py,sha256=ipAZ1DUd5CMTpUoxRXHVOFC3DKIpxwxpTYAfrOJ6UZ8,9829
84
88
  sticker_convert/utils/auth/get_line_auth.py,sha256=8l8ha2vQmk3rHGvDE7PkcxQXbH3oe62LKbI3qVUtvqc,2196
85
89
  sticker_convert/utils/auth/get_signal_auth.py,sha256=6Sx-lMuyBHeX1RpjAWI8u03qnRu9fmO4p89pd7fowOE,4925
90
+ sticker_convert/utils/auth/get_viber_auth.py,sha256=UUdnESATVGj-mrDuM_5wq75ouQFqPvFtdyqjGDqxi5Y,13734
86
91
  sticker_convert/utils/files/cache_store.py,sha256=etfe614OAhAyrnM5fGeESKq6R88YLNqkqkxSzEmZ0V0,1047
87
92
  sticker_convert/utils/files/json_manager.py,sha256=Vr6pZJdLMkrJJWN99210aduVHb0ILyf0SSTaw4TZqgc,541
88
93
  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
94
+ sticker_convert/utils/files/metadata_handler.py,sha256=KDwzCwSckTob2VacOvzLdu1256WLicmzXgkhfFvRBzo,10108
90
95
  sticker_convert/utils/files/run_bin.py,sha256=QalA9je6liHxiOtxsjsFsIkc2t59quhcJCVpP1X3p50,1743
91
96
  sticker_convert/utils/files/sanitize_filename.py,sha256=HBklPGsHRJjFQUIC5rYTQsUrsuTtezZXIEA8CPhLP8A,2156
92
97
  sticker_convert/utils/media/apple_png_normalize.py,sha256=LbrQhc7LlYX4I9ek4XJsZE4l0MygBA1jB-PFiYLEkzk,3657
93
98
  sticker_convert/utils/media/codec_info.py,sha256=1QfW3wgZ5vOk7T4XtLHYvJK1x8RbASRPSvhKEPkcu9A,15747
94
99
  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.14.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
97
- sticker_convert-2.8.14.dist-info/METADATA,sha256=oMOCYbDpT4foe2pN0gsrfAAG1DASm8ak3uUjc9tpCpA,50376
98
- sticker_convert-2.8.14.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
99
- sticker_convert-2.8.14.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
100
- sticker_convert-2.8.14.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
101
- sticker_convert-2.8.14.dist-info/RECORD,,
100
+ sticker_convert/utils/media/format_verify.py,sha256=MH68GLJfXeL8WFT8emtj355K5BLAtUX64tQ59nugx2c,5673
101
+ sticker_convert-2.9.1.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
102
+ sticker_convert-2.9.1.dist-info/METADATA,sha256=Sim5kcFjuwRWedkvQhuAIyCMmpYRQ-bA3cAIqQiZuFw,51091
103
+ sticker_convert-2.9.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
104
+ sticker_convert-2.9.1.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
105
+ sticker_convert-2.9.1.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
106
+ sticker_convert-2.9.1.dist-info/RECORD,,