session-python 1.0.1__tar.gz → 1.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. {session_python-1.0.1/session_python.egg-info → session_python-1.0.3}/PKG-INFO +32 -1
  2. {session_python-1.0.1 → session_python-1.0.3}/README.md +31 -0
  3. {session_python-1.0.1 → session_python-1.0.3}/pyproject.toml +4 -1
  4. session_python-1.0.3/session_python/cli.py +233 -0
  5. {session_python-1.0.1 → session_python-1.0.3/session_python.egg-info}/PKG-INFO +32 -1
  6. {session_python-1.0.1 → session_python-1.0.3}/session_python.egg-info/SOURCES.txt +2 -0
  7. session_python-1.0.3/session_python.egg-info/entry_points.txt +2 -0
  8. {session_python-1.0.1 → session_python-1.0.3}/LICENSE +0 -0
  9. {session_python-1.0.1 → session_python-1.0.3}/session_python/__init__.py +0 -0
  10. {session_python-1.0.1 → session_python-1.0.3}/session_python/client.py +0 -0
  11. {session_python-1.0.1 → session_python-1.0.3}/session_python/crypto.py +0 -0
  12. {session_python-1.0.1 → session_python-1.0.3}/session_python/mnemonic.py +0 -0
  13. {session_python-1.0.1 → session_python-1.0.3}/session_python/network.py +0 -0
  14. {session_python-1.0.1 → session_python-1.0.3}/session_python/polling.py +0 -0
  15. {session_python-1.0.1 → session_python-1.0.3}/session_python/protobuf/__init__.py +0 -0
  16. {session_python-1.0.1 → session_python-1.0.3}/session_python/protobuf/signalservice_pb2.py +0 -0
  17. {session_python-1.0.1 → session_python-1.0.3}/session_python.egg-info/dependency_links.txt +0 -0
  18. {session_python-1.0.1 → session_python-1.0.3}/session_python.egg-info/requires.txt +0 -0
  19. {session_python-1.0.1 → session_python-1.0.3}/session_python.egg-info/top_level.txt +0 -0
  20. {session_python-1.0.1 → session_python-1.0.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: session-python
3
- Version: 1.0.1
3
+ Version: 1.0.3
4
4
  Summary: A pure Python implementation of the Session Messenger protocol client
5
5
  Author-email: Towux <towux@users.noreply.github.com>
6
6
  Project-URL: Homepage, https://github.com/towux/session-python
@@ -148,8 +148,39 @@ with Session(proxy=PROXY) as session:
148
148
  session.delete_message(conversation=RECIPIENT_ID, timestamp=1783586415070, hash_val="IXFgLeoj...")
149
149
  ```
150
150
 
151
+ ## 💻 Command Line Interface (CLI)
152
+
153
+ The package installs a command-line tool `sscli` to manage mnemonics and generate accounts directly from the terminal.
154
+
155
+ ### 1. Generate a new Session ID and Mnemonic
156
+ ```bash
157
+ sscli mnemonic gen
158
+ ```
159
+
160
+ ### 2. Generate a Vanity Session ID (Prefix Brute-force)
161
+ Find custom Session IDs. By default, this uses all available CPU threads for maximum performance:
162
+ ```bash
163
+ # Find a Session ID starting with '05abc...'
164
+ sscli mnemonic gen -p abc
165
+
166
+ # Generate 3 accounts starting with '0577...' using 2 threads
167
+ sscli mnemonic gen -p 77 -n 3 -t 2
168
+ ```
169
+
170
+ ### 3. Derive Session ID from existing mnemonic
171
+ ```bash
172
+ sscli mnemonic gen "your 13 word mnemonic here..."
173
+ ```
174
+
175
+ ### 4. Verify a mnemonic
176
+ Validates the checksum and words of a mnemonic, and outputs its hex seed and Session ID:
177
+ ```bash
178
+ sscli mnemonic verify "your 13 word mnemonic here..."
179
+ ```
180
+
151
181
  ---
152
182
 
183
+
153
184
  ## ⚖️ License
154
185
 
155
186
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -126,8 +126,39 @@ with Session(proxy=PROXY) as session:
126
126
  session.delete_message(conversation=RECIPIENT_ID, timestamp=1783586415070, hash_val="IXFgLeoj...")
127
127
  ```
128
128
 
129
+ ## 💻 Command Line Interface (CLI)
130
+
131
+ The package installs a command-line tool `sscli` to manage mnemonics and generate accounts directly from the terminal.
132
+
133
+ ### 1. Generate a new Session ID and Mnemonic
134
+ ```bash
135
+ sscli mnemonic gen
136
+ ```
137
+
138
+ ### 2. Generate a Vanity Session ID (Prefix Brute-force)
139
+ Find custom Session IDs. By default, this uses all available CPU threads for maximum performance:
140
+ ```bash
141
+ # Find a Session ID starting with '05abc...'
142
+ sscli mnemonic gen -p abc
143
+
144
+ # Generate 3 accounts starting with '0577...' using 2 threads
145
+ sscli mnemonic gen -p 77 -n 3 -t 2
146
+ ```
147
+
148
+ ### 3. Derive Session ID from existing mnemonic
149
+ ```bash
150
+ sscli mnemonic gen "your 13 word mnemonic here..."
151
+ ```
152
+
153
+ ### 4. Verify a mnemonic
154
+ Validates the checksum and words of a mnemonic, and outputs its hex seed and Session ID:
155
+ ```bash
156
+ sscli mnemonic verify "your 13 word mnemonic here..."
157
+ ```
158
+
129
159
  ---
130
160
 
161
+
131
162
  ## ⚖️ License
132
163
 
133
164
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "session-python"
7
- version = "1.0.1"
7
+ version = "1.0.3"
8
8
  description = "A pure Python implementation of the Session Messenger protocol client"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -26,6 +26,9 @@ dependencies = [
26
26
  "pysocks>=1.7.1"
27
27
  ]
28
28
 
29
+ [project.scripts]
30
+ sscli = "session_python.cli:main"
31
+
29
32
  [project.urls]
30
33
  "Homepage" = "https://github.com/towux/session-python"
31
34
  "Bug Tracker" = "https://github.com/towux/session-python/issues"
@@ -0,0 +1,233 @@
1
+ import argparse
2
+ import time
3
+ import os
4
+ import binascii
5
+ import ctypes
6
+ import multiprocessing
7
+ import nacl.signing
8
+ from rich.console import Console
9
+ from rich.live import Live
10
+ from rich.text import Text
11
+ from .client import Session
12
+ from .mnemonic import encode as encode_mnemonic, decode as decode_mnemonic
13
+
14
+ def format_time(seconds: float) -> str:
15
+ if seconds <= 0:
16
+ return "0s"
17
+ MINUTE = 60
18
+ HOUR = 3600
19
+ DAY = 86400
20
+ MONTH = 2592000 # 30 days
21
+ YEAR = 31536000 # 365 days
22
+
23
+ if seconds < MINUTE:
24
+ return f"{seconds:.0f}s"
25
+ if seconds < HOUR:
26
+ m = int(seconds // MINUTE)
27
+ s = int(seconds % MINUTE)
28
+ return f"{m}m {s}s"
29
+ if seconds < DAY:
30
+ h = int(seconds // HOUR)
31
+ m = int((seconds % HOUR) // MINUTE)
32
+ return f"{h}h {m}m"
33
+ if seconds < MONTH:
34
+ d = int(seconds // DAY)
35
+ h = int((seconds % DAY) // HOUR)
36
+ return f"{d}d {h}h"
37
+ if seconds < YEAR:
38
+ mo = int(seconds // MONTH)
39
+ d = int((seconds % MONTH) // DAY)
40
+ return f"{mo}mo {d}d"
41
+
42
+ y = int(seconds // YEAR)
43
+ mo = int((seconds % YEAR) // MONTH)
44
+ return f"{y}y {mo}mo"
45
+
46
+ def search_worker(prefix: str, result_queue: multiprocessing.Queue, checked_counter: multiprocessing.Value, stop_event: multiprocessing.Event):
47
+ """
48
+ Worker process for brute-forcing vanity Session IDs.
49
+ """
50
+ import os
51
+ import binascii
52
+ import nacl.signing
53
+ from .mnemonic import encode as encode_mnemonic
54
+
55
+ local_checked = 0
56
+ while not stop_event.is_set():
57
+ local_checked += 1
58
+ seed_16 = os.urandom(16)
59
+
60
+ # Derive Session ID
61
+ seed_32_hex = binascii.hexlify(seed_16).decode('utf-8') + "00000000000000000000000000000000"
62
+ seed_32 = binascii.unhexlify(seed_32_hex)
63
+
64
+ signing_key = nacl.signing.SigningKey(seed_32)
65
+ x25519_pub = signing_key.verify_key.to_curve25519_public_key()
66
+ session_id = "05" + x25519_pub.encode().hex()
67
+
68
+ if session_id[2:].startswith(prefix):
69
+ mnemonic = encode_mnemonic(binascii.hexlify(seed_16).decode('utf-8'))
70
+ result_queue.put((session_id, mnemonic))
71
+ stop_event.set()
72
+ break
73
+
74
+ # Update shared counter periodically to avoid locking bottleneck
75
+ if local_checked >= 2000:
76
+ with checked_counter.get_lock():
77
+ checked_counter.value += local_checked
78
+ local_checked = 0
79
+
80
+ if local_checked > 0:
81
+ with checked_counter.get_lock():
82
+ checked_counter.value += local_checked
83
+
84
+ def main():
85
+ multiprocessing.freeze_support()
86
+
87
+ max_threads = os.cpu_count() or 1
88
+
89
+ parser = argparse.ArgumentParser(
90
+ description="Session Python CLI - Command Line interface for Session Messenger"
91
+ )
92
+ subparsers = parser.add_subparsers(dest="command", help="Sub-commands")
93
+
94
+ # 'mnemonic' group command
95
+ mnemonic_parser = subparsers.add_parser("mnemonic", help="Mnemonic and account key utilities")
96
+ mnemonic_subparsers = mnemonic_parser.add_subparsers(dest="subcommand", help="Sub-commands of mnemonic")
97
+
98
+ # 'mnemonic verify'
99
+ verify_parser = mnemonic_subparsers.add_parser("verify", help="Verify a 13-word mnemonic")
100
+ verify_parser.add_argument("words", type=str, help="The 13-word mnemonic to verify")
101
+
102
+ # 'mnemonic gen'
103
+ gen_parser = mnemonic_subparsers.add_parser("gen", help="Generate new mnemonics or derive ID from existing mnemonic")
104
+ gen_parser.add_argument("words", type=str, nargs="?", default=None, help="Optional existing 13-word mnemonic to derive ID from")
105
+ gen_parser.add_argument(
106
+ "-n",
107
+ type=int,
108
+ default=1,
109
+ help="Number of accounts to generate (1 to 100)"
110
+ )
111
+ gen_parser.add_argument(
112
+ "-p", "--prefix",
113
+ type=str,
114
+ default="",
115
+ help="Prefix the generated Session ID must start with (after 05, hex only, e.g. 'abc')"
116
+ )
117
+ gen_parser.add_argument(
118
+ "-t", "--threads",
119
+ type=int,
120
+ default=0,
121
+ help=f"Number of CPU threads to use (1 to {max_threads}, 0 for all cores, default: 0)"
122
+ )
123
+
124
+ args = parser.parse_args()
125
+ console = Console()
126
+
127
+ if args.command == "mnemonic":
128
+ if args.subcommand == "verify":
129
+ words = args.words.strip()
130
+ try:
131
+ seed_hex = decode_mnemonic(words)
132
+ # Derive Session ID
133
+ session = Session()
134
+ session.set_mnemonic(words)
135
+ session_id = session.get_session_id()
136
+ console.print("[bold green]Valid Mnemonic![/bold green]")
137
+ console.print(f"Session ID: {session_id}")
138
+ console.print(f"Hex Seed: {seed_hex}")
139
+ except ValueError as e:
140
+ console.print(f"[bold red]Invalid Mnemonic:[/bold red] {e}")
141
+
142
+ elif args.subcommand == "gen":
143
+ words = args.words.strip() if args.words else None
144
+
145
+ if words:
146
+ # Derive Session ID for provided mnemonic
147
+ try:
148
+ session = Session()
149
+ session.set_mnemonic(words)
150
+ session_id = session.get_session_id()
151
+ console.print(f"{session_id} - {words}")
152
+ except ValueError as e:
153
+ console.print(f"[bold red]Error deriving ID:[/bold red] {e}")
154
+ else:
155
+ # Generate new accounts (vanity search or instant)
156
+ count = args.n
157
+ if count < 1 or count > 100:
158
+ parser.error("The number of accounts (-n) must be between 1 and 100.")
159
+
160
+ threads_arg = args.threads
161
+ if threads_arg < 0 or threads_arg > max_threads:
162
+ parser.error(f"The number of threads (-t/--threads) must be between 0 and {max_threads} (your CPU has {max_threads} cores).")
163
+
164
+ num_workers = max_threads if threads_arg == 0 else threads_arg
165
+
166
+ prefix = args.prefix.lower() if args.prefix else ""
167
+ if prefix:
168
+ if not all(c in "0123456789abcdef" for c in prefix):
169
+ parser.error("The prefix (-p/--prefix) must contain only valid hex characters (0-9, a-f).")
170
+
171
+ for _ in range(count):
172
+ if prefix:
173
+ start_time = time.time()
174
+ total_expected = 16 ** len(prefix)
175
+
176
+ # Shared resources for multiprocessing
177
+ result_queue = multiprocessing.Queue()
178
+ checked_counter = multiprocessing.Value(ctypes.c_uint64, 0)
179
+ stop_event = multiprocessing.Event()
180
+
181
+ # Spawn workers
182
+ processes = []
183
+ for _ in range(num_workers):
184
+ p = multiprocessing.Process(
185
+ target=search_worker,
186
+ args=(prefix, result_queue, checked_counter, stop_event)
187
+ )
188
+ p.daemon = True
189
+ p.start()
190
+ processes.append(p)
191
+
192
+ with Live(Text("Initializing search...", style="yellow"), refresh_per_second=10) as live:
193
+ while not stop_event.is_set() and result_queue.empty():
194
+ time.sleep(0.1)
195
+ checked = checked_counter.value
196
+ elapsed = time.time() - start_time
197
+ speed = checked / elapsed if elapsed > 0 else 0
198
+
199
+ if checked < total_expected:
200
+ remaining_checks = total_expected - checked
201
+ remaining_seconds = remaining_checks / speed if speed > 0 else 0
202
+ eta_str = format_time(remaining_seconds)
203
+ else:
204
+ avg_seconds = total_expected / speed if speed > 0 else 0
205
+ eta_str = f"running over (avg {format_time(avg_seconds)})"
206
+
207
+ live.update(Text(
208
+ f"Searching for ID starting with '05{prefix}' ({num_workers} threads)...\n"
209
+ f"Speed: {speed:.1f} id/sec | Checked: {checked}/{total_expected} | Time: {elapsed:.1f}s | ETA: {eta_str}",
210
+ style="cyan"
211
+ ))
212
+
213
+ # Retrieve result and cleanup processes
214
+ session_id, mnemonic = result_queue.get()
215
+ for p in processes:
216
+ if p.is_alive():
217
+ p.terminate()
218
+
219
+ console.print(f"[bold green]{session_id}[/bold green] - [bold white]{mnemonic}[/bold white]")
220
+ else:
221
+ # Instant generation without prefix
222
+ mnemonic = Session.generate_mnemonic()
223
+ session = Session()
224
+ session.set_mnemonic(mnemonic)
225
+ session_id = session.get_session_id()
226
+ console.print(f"[bold green]{session_id}[/bold green] - [bold white]{mnemonic}[/bold white]")
227
+ else:
228
+ mnemonic_parser.print_help()
229
+ else:
230
+ parser.print_help()
231
+
232
+ if __name__ == "__main__":
233
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: session-python
3
- Version: 1.0.1
3
+ Version: 1.0.3
4
4
  Summary: A pure Python implementation of the Session Messenger protocol client
5
5
  Author-email: Towux <towux@users.noreply.github.com>
6
6
  Project-URL: Homepage, https://github.com/towux/session-python
@@ -148,8 +148,39 @@ with Session(proxy=PROXY) as session:
148
148
  session.delete_message(conversation=RECIPIENT_ID, timestamp=1783586415070, hash_val="IXFgLeoj...")
149
149
  ```
150
150
 
151
+ ## 💻 Command Line Interface (CLI)
152
+
153
+ The package installs a command-line tool `sscli` to manage mnemonics and generate accounts directly from the terminal.
154
+
155
+ ### 1. Generate a new Session ID and Mnemonic
156
+ ```bash
157
+ sscli mnemonic gen
158
+ ```
159
+
160
+ ### 2. Generate a Vanity Session ID (Prefix Brute-force)
161
+ Find custom Session IDs. By default, this uses all available CPU threads for maximum performance:
162
+ ```bash
163
+ # Find a Session ID starting with '05abc...'
164
+ sscli mnemonic gen -p abc
165
+
166
+ # Generate 3 accounts starting with '0577...' using 2 threads
167
+ sscli mnemonic gen -p 77 -n 3 -t 2
168
+ ```
169
+
170
+ ### 3. Derive Session ID from existing mnemonic
171
+ ```bash
172
+ sscli mnemonic gen "your 13 word mnemonic here..."
173
+ ```
174
+
175
+ ### 4. Verify a mnemonic
176
+ Validates the checksum and words of a mnemonic, and outputs its hex seed and Session ID:
177
+ ```bash
178
+ sscli mnemonic verify "your 13 word mnemonic here..."
179
+ ```
180
+
151
181
  ---
152
182
 
183
+
153
184
  ## ⚖️ License
154
185
 
155
186
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -2,6 +2,7 @@ LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
4
  session_python/__init__.py
5
+ session_python/cli.py
5
6
  session_python/client.py
6
7
  session_python/crypto.py
7
8
  session_python/mnemonic.py
@@ -10,6 +11,7 @@ session_python/polling.py
10
11
  session_python.egg-info/PKG-INFO
11
12
  session_python.egg-info/SOURCES.txt
12
13
  session_python.egg-info/dependency_links.txt
14
+ session_python.egg-info/entry_points.txt
13
15
  session_python.egg-info/requires.txt
14
16
  session_python.egg-info/top_level.txt
15
17
  session_python/protobuf/__init__.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ sscli = session_python.cli:main
File without changes
File without changes