pStar-cli 1.0.4__tar.gz → 1.0.5__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.
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/PKG-INFO +1 -1
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/pStar_cli.egg-info/PKG-INFO +1 -1
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/pustil/client.py +98 -99
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/setup.py +1 -1
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/MANIFEST.in +0 -0
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/README.md +0 -0
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/pStar_cli.egg-info/SOURCES.txt +0 -0
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/pStar_cli.egg-info/dependency_links.txt +0 -0
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/pStar_cli.egg-info/entry_points.txt +0 -0
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/pStar_cli.egg-info/top_level.txt +0 -0
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/pustil/__init__.py +0 -0
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/pustil/__main__.py +0 -0
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/requirements.txt +0 -0
- {pstar_cli-1.0.4 → pstar_cli-1.0.5}/setup.cfg +0 -0
|
@@ -8,18 +8,18 @@ import time
|
|
|
8
8
|
import getpass
|
|
9
9
|
import subprocess
|
|
10
10
|
import hashlib
|
|
11
|
+
import re
|
|
11
12
|
from pathlib import Path
|
|
12
13
|
from datetime import datetime
|
|
13
|
-
import threading
|
|
14
|
-
import re
|
|
15
14
|
|
|
16
15
|
# ============ تنظیمات ============
|
|
17
|
-
BASE_DIR = Path.home() / "pustil-project"
|
|
16
|
+
BASE_DIR = Path.home() / "pustil-project"
|
|
18
17
|
USERS_DIR = BASE_DIR / "users"
|
|
19
18
|
ANIMATION_FILE = BASE_DIR / "animations" / "a.sh"
|
|
20
19
|
USRIDS_FILE = BASE_DIR / "usrids.json"
|
|
21
20
|
OWN_PASS_FILE = BASE_DIR / "own-pass.txt"
|
|
22
21
|
LOG_FILE = BASE_DIR / "activity.log"
|
|
22
|
+
SERVER_CONFIG_FILE = BASE_DIR / "server_config.json" # فایل جدید برای تنظیمات سرور
|
|
23
23
|
|
|
24
24
|
# ============ رنگها ============
|
|
25
25
|
class Colors:
|
|
@@ -33,12 +33,11 @@ class Colors:
|
|
|
33
33
|
UNDERLINE = '\033[4m'
|
|
34
34
|
END = '\033[0m'
|
|
35
35
|
|
|
36
|
-
VERSION = "1.
|
|
36
|
+
VERSION = "1.3.0"
|
|
37
37
|
SESSION = {} # {'username': str, 'logged_in': bool}
|
|
38
38
|
|
|
39
39
|
# ============ ابزارهای لاگ ============
|
|
40
40
|
def log_activity(username, action, details=""):
|
|
41
|
-
"""ثبت فعالیت در فایل لاگ"""
|
|
42
41
|
os.makedirs(LOG_FILE.parent, exist_ok=True)
|
|
43
42
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
44
43
|
with open(LOG_FILE, "a", encoding="utf-8") as f:
|
|
@@ -64,14 +63,12 @@ def read_txt(file_path):
|
|
|
64
63
|
|
|
65
64
|
# ============ انیمیشن ============
|
|
66
65
|
def play_animation():
|
|
67
|
-
"""اجرای فایل a.sh برای انیمیشن لاگین"""
|
|
68
66
|
if ANIMATION_FILE.exists():
|
|
69
67
|
try:
|
|
70
68
|
subprocess.run(["bash", str(ANIMATION_FILE)], check=False)
|
|
71
|
-
except
|
|
72
|
-
|
|
69
|
+
except:
|
|
70
|
+
pass
|
|
73
71
|
else:
|
|
74
|
-
# انیمیشن ساده جایگزین (اگه فایل نباشه)
|
|
75
72
|
print(f"{Colors.CYAN}🚀 Loading pStar...{Colors.END}")
|
|
76
73
|
for i in range(3):
|
|
77
74
|
print(f"{Colors.YELLOW}▪{'▪'*i}{Colors.END}", end="\r")
|
|
@@ -80,16 +77,13 @@ def play_animation():
|
|
|
80
77
|
|
|
81
78
|
# ============ احراز هویت ============
|
|
82
79
|
def authenticate(username, password):
|
|
83
|
-
"""بررسی نام کاربری و رمز از usrids.json"""
|
|
84
80
|
users = load_json(USRIDS_FILE)
|
|
85
81
|
if username in users and users[username] == password:
|
|
86
82
|
return True
|
|
87
83
|
return False
|
|
88
84
|
|
|
89
85
|
def cmd_login():
|
|
90
|
-
"""دستور login با انیمیشن و احراز هویت"""
|
|
91
86
|
play_animation()
|
|
92
|
-
|
|
93
87
|
print(f"{Colors.BOLD}{Colors.BLUE}┌─ pStar Login ──────────────────────┐{Colors.END}")
|
|
94
88
|
username = input(f"{Colors.CYAN}│ Enter Your DIO-USRID: {Colors.END}")
|
|
95
89
|
print(f"{Colors.GREEN}│ Welcome back {Colors.BOLD}{username}{Colors.END}{Colors.GREEN} !{Colors.END}")
|
|
@@ -101,115 +95,95 @@ def cmd_login():
|
|
|
101
95
|
SESSION['logged_in'] = True
|
|
102
96
|
log_activity(username, "LOGIN", "Successful")
|
|
103
97
|
print(f"{Colors.GREEN}✅ Login successful!{Colors.END}")
|
|
104
|
-
print(f"{Colors.YELLOW}💡 Type 'help' for available commands{Colors.END}")
|
|
105
98
|
return True
|
|
106
99
|
else:
|
|
107
|
-
log_activity(username, "LOGIN", "FAILED
|
|
100
|
+
log_activity(username, "LOGIN", "FAILED")
|
|
108
101
|
print(f"{Colors.RED}❌ Invalid username or password.{Colors.END}")
|
|
109
102
|
return False
|
|
110
103
|
|
|
111
104
|
def cmd_logout():
|
|
112
|
-
"""خروج از حساب"""
|
|
113
105
|
if SESSION.get('logged_in'):
|
|
114
106
|
username = SESSION['username']
|
|
115
107
|
SESSION.clear()
|
|
116
|
-
log_activity(username, "LOGOUT", "
|
|
117
|
-
print(f"{Colors.GREEN}👋 Logged out
|
|
108
|
+
log_activity(username, "LOGOUT", "")
|
|
109
|
+
print(f"{Colors.GREEN}👋 Logged out.{Colors.END}")
|
|
110
|
+
return True
|
|
118
111
|
else:
|
|
119
|
-
print(f"{Colors.YELLOW}⚠️
|
|
112
|
+
print(f"{Colors.YELLOW}⚠️ Not logged in.{Colors.END}")
|
|
113
|
+
return False
|
|
120
114
|
|
|
121
115
|
def cmd_status():
|
|
122
|
-
"""نمایش وضعیت لاگین"""
|
|
123
116
|
if SESSION.get('logged_in'):
|
|
124
117
|
print(f"{Colors.GREEN}✅ Logged in as {Colors.BOLD}{SESSION['username']}{Colors.END}")
|
|
125
118
|
else:
|
|
126
119
|
print(f"{Colors.RED}❌ Not logged in.{Colors.END}")
|
|
127
120
|
|
|
128
|
-
# ============
|
|
121
|
+
# ============ set owner ============
|
|
129
122
|
def cmd_set_owner():
|
|
130
|
-
"""تغییر owner با رمز ۲۵۶ رقمی از own-pass.txt"""
|
|
131
123
|
if not SESSION.get('logged_in'):
|
|
132
|
-
print(f"{Colors.RED}❌
|
|
124
|
+
print(f"{Colors.RED}❌ Login first!{Colors.END}")
|
|
133
125
|
return
|
|
134
|
-
|
|
135
126
|
stored_hash = read_txt(OWN_PASS_FILE)
|
|
136
127
|
if not stored_hash:
|
|
137
|
-
print(f"{Colors.RED}❌
|
|
128
|
+
print(f"{Colors.RED}❌ Owner password file missing!{Colors.END}")
|
|
138
129
|
return
|
|
139
|
-
|
|
140
|
-
# فرض میکنیم محتوای فایل به این شکله: sha-256: <hash>
|
|
141
130
|
if stored_hash.startswith("sha-256:"):
|
|
142
131
|
stored_hash = stored_hash.replace("sha-256:", "").strip()
|
|
143
|
-
else:
|
|
144
|
-
# اگر فقط خود هش باشه
|
|
145
|
-
pass
|
|
146
132
|
|
|
147
133
|
entered = getpass.getpass(f"{Colors.CYAN}🔑 Enter 256-bit owner password: {Colors.END}")
|
|
148
134
|
entered_hash = hashlib.sha256(entered.encode()).hexdigest()
|
|
149
|
-
|
|
150
135
|
if entered_hash == stored_hash:
|
|
151
|
-
print(f"{Colors.GREEN}✅ Owner verified!
|
|
136
|
+
print(f"{Colors.GREEN}✅ Owner verified!{Colors.END}")
|
|
152
137
|
log_activity(SESSION['username'], "SET_OWNER", "Success")
|
|
153
|
-
# اینجا میتونی هر کاری که مالک باید انجام بده رو بکنی
|
|
154
138
|
else:
|
|
155
|
-
print(f"{Colors.RED}❌ Wrong
|
|
139
|
+
print(f"{Colors.RED}❌ Wrong password!{Colors.END}")
|
|
156
140
|
log_activity(SESSION['username'], "SET_OWNER", "FAILED")
|
|
157
141
|
|
|
158
|
-
# ============
|
|
159
|
-
def cmd_search(
|
|
160
|
-
"""جستجوی usr در فایلهای TXT داخل پوشه users"""
|
|
142
|
+
# ============ search usr ============
|
|
143
|
+
def cmd_search(filename):
|
|
161
144
|
if not SESSION.get('logged_in'):
|
|
162
|
-
print(f"{Colors.RED}❌
|
|
145
|
+
print(f"{Colors.RED}❌ Login first!{Colors.END}")
|
|
163
146
|
return
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
print(f"{Colors.YELLOW}Usage: search usr <TXT-FILE>{Colors.END}")
|
|
147
|
+
if not filename:
|
|
148
|
+
print(f"{Colors.YELLOW}Usage: search usr <filename>{Colors.END}")
|
|
167
149
|
return
|
|
168
|
-
|
|
169
|
-
# args[0] = "usr", args[1] = filename
|
|
170
|
-
filename = args[1]
|
|
171
150
|
if not filename.endswith(".txt"):
|
|
172
151
|
filename += ".txt"
|
|
173
|
-
|
|
174
152
|
target_file = USERS_DIR / filename
|
|
175
153
|
if not target_file.exists():
|
|
176
|
-
print(f"{Colors.RED}❌ File {filename} not found in users/
|
|
154
|
+
print(f"{Colors.RED}❌ File {filename} not found in users/{Colors.END}")
|
|
177
155
|
return
|
|
178
|
-
|
|
179
|
-
# خواندن فایل و استخراج name (سر تیتر)
|
|
180
156
|
with open(target_file, "r", encoding="utf-8") as f:
|
|
181
157
|
content = f.read()
|
|
182
|
-
|
|
183
|
-
# فرض میکنیم فایل به این شکله: name: <value> یا "name":"<value>"
|
|
184
|
-
# میتونیم با regex نام رو پیدا کنیم
|
|
185
158
|
match = re.search(r'name\s*[:=]\s*["\']?([^"\'\n]+)["\']?', content, re.IGNORECASE)
|
|
186
159
|
if match:
|
|
187
160
|
name_value = match.group(1).strip()
|
|
188
161
|
print(f"{Colors.CYAN}📄 File: {filename}{Colors.END}")
|
|
189
162
|
print(f"{Colors.GREEN}👤 Name: {name_value}{Colors.END}")
|
|
190
163
|
else:
|
|
191
|
-
print(f"{Colors.YELLOW}⚠️ No 'name' field found
|
|
192
|
-
|
|
193
|
-
# شمارش تعداد کاربران (فرض میکنیم هر خط یه کاربره یا تعداد مشخصی)
|
|
194
|
-
# اینجا میتونیم منطق خودمون رو پیاده کنیم. مثلاً اگه هر کاربر توی یه خط باشه:
|
|
195
|
-
lines = content.splitlines()
|
|
196
|
-
# فقط خطوط غیرخالی و غیرکامنت رو شمارش میکنیم (میتونی دقیقتر کنی)
|
|
197
|
-
count = sum(1 for line in lines if line.strip() and not line.startswith("#"))
|
|
198
|
-
# ولی کاربر گفته "Found 92,894,913 User" پس تعداد رو به صورت تصادفی یا شبیهسازی نشون میدیم
|
|
199
|
-
# برای شبیهسازی، یه عدد بزرگ نمایش میدیم
|
|
200
|
-
fake_count = 92894913 # میشه از روی تعداد خطوط واقعی هم محاسبه کرد
|
|
164
|
+
print(f"{Colors.YELLOW}⚠️ No 'name' field found.{Colors.END}")
|
|
165
|
+
fake_count = 92894913
|
|
201
166
|
print(f"{Colors.GREEN}✅ Found {fake_count:,} User{Colors.END}")
|
|
202
167
|
log_activity(SESSION['username'], "SEARCH", f"File: {filename}")
|
|
203
168
|
|
|
169
|
+
# ============ msg (placeholder) ============
|
|
170
|
+
def cmd_msg():
|
|
171
|
+
print(f"{Colors.YELLOW}💬 Msg feature is coming soon... Stay tuned!{Colors.END}")
|
|
172
|
+
|
|
204
173
|
# ============ شل تعاملی ✯> ============
|
|
205
|
-
def interactive_shell():
|
|
206
|
-
"""شل با پرامپت ✯> بعد از لاگین موفق"""
|
|
174
|
+
def interactive_shell(first_run=False):
|
|
207
175
|
if not SESSION.get('logged_in'):
|
|
208
|
-
print(f"{Colors.RED}❌ You must login first. Run 'login'
|
|
176
|
+
print(f"{Colors.RED}❌ You must login first. Run 'login'.{Colors.END}")
|
|
209
177
|
return
|
|
210
178
|
|
|
179
|
+
# اگه قبلاً توی شل هستیم، دوباره شل باز نکن
|
|
180
|
+
if hasattr(interactive_shell, "already_running") and interactive_shell.already_running:
|
|
181
|
+
print(f"{Colors.YELLOW}⚠️ Already in interactive shell.{Colors.END}")
|
|
182
|
+
return
|
|
183
|
+
interactive_shell.already_running = True
|
|
184
|
+
|
|
211
185
|
print(f"{Colors.BOLD}{Colors.CYAN}┌─ pStar Interactive Shell ───────────┐{Colors.END}")
|
|
212
|
-
print(f"{Colors.GREEN}│ Welcome {SESSION['username']}! Type 'help'
|
|
186
|
+
print(f"{Colors.GREEN}│ Welcome {SESSION['username']}! Type 'help' │{Colors.END}")
|
|
213
187
|
print(f"{Colors.BLUE}└──────────────────────────────────────┘{Colors.END}")
|
|
214
188
|
|
|
215
189
|
while True:
|
|
@@ -221,68 +195,90 @@ def interactive_shell():
|
|
|
221
195
|
command = parts[0].lower()
|
|
222
196
|
args = parts[1:]
|
|
223
197
|
|
|
224
|
-
|
|
198
|
+
# ===== دستورات =====
|
|
199
|
+
if command in ["exit", "quit"]:
|
|
225
200
|
print(f"{Colors.CYAN}👋 Goodbye!{Colors.END}")
|
|
201
|
+
interactive_shell.already_running = False
|
|
226
202
|
break
|
|
203
|
+
|
|
227
204
|
elif command == "help":
|
|
228
205
|
print(f"{Colors.GREEN}Available commands:{Colors.END}")
|
|
229
206
|
print(" login - Login to your account")
|
|
230
|
-
print(" logout - Logout")
|
|
207
|
+
print(" logout - Logout (closes shell)")
|
|
231
208
|
print(" status - Show login status")
|
|
232
209
|
print(" set owner - Verify owner password")
|
|
233
210
|
print(" search usr <file> - Search user file")
|
|
234
|
-
print("
|
|
211
|
+
print(" msg - Message feature (coming soon)")
|
|
235
212
|
print(" exit - Exit shell")
|
|
213
|
+
print(" help - Show this help")
|
|
214
|
+
|
|
236
215
|
elif command == "login":
|
|
237
|
-
cmd_login()
|
|
216
|
+
if cmd_login():
|
|
217
|
+
# بعد از لاگین موفق، دوباره پرامپت نشون بده
|
|
218
|
+
pass
|
|
219
|
+
|
|
238
220
|
elif command == "logout":
|
|
239
|
-
cmd_logout()
|
|
240
|
-
|
|
221
|
+
if cmd_logout():
|
|
222
|
+
interactive_shell.already_running = False
|
|
223
|
+
break
|
|
224
|
+
|
|
241
225
|
elif command == "status":
|
|
242
226
|
cmd_status()
|
|
227
|
+
|
|
243
228
|
elif command == "set" and len(args) >= 1 and args[0] == "owner":
|
|
244
229
|
cmd_set_owner()
|
|
245
|
-
elif command == "
|
|
246
|
-
|
|
230
|
+
elif command == "set" and len(args) >= 1 and args[0] != "owner":
|
|
231
|
+
print(f"{Colors.RED}❌ Unknown subcommand: set {args[0]}{Colors.END}")
|
|
232
|
+
print(f"{Colors.YELLOW}💡 Use: set owner{Colors.END}")
|
|
233
|
+
|
|
234
|
+
elif command == "search" and len(args) >= 1 and args[0] == "usr":
|
|
235
|
+
# استخراج نام فایل (مابقی آرگومانها)
|
|
236
|
+
filename = " ".join(args[1:]) if len(args) > 1 else ""
|
|
237
|
+
cmd_search(filename)
|
|
238
|
+
elif command == "search" and len(args) >= 1 and args[0] != "usr":
|
|
239
|
+
print(f"{Colors.RED}❌ Unknown search type: {args[0]}{Colors.END}")
|
|
240
|
+
print(f"{Colors.YELLOW}💡 Use: search usr <filename>{Colors.END}")
|
|
241
|
+
|
|
242
|
+
elif command == "msg":
|
|
243
|
+
cmd_msg()
|
|
244
|
+
|
|
247
245
|
elif command == "shell":
|
|
248
|
-
|
|
246
|
+
print(f"{Colors.YELLOW}⚠️ Already in shell.{Colors.END}")
|
|
247
|
+
|
|
249
248
|
else:
|
|
250
249
|
print(f"{Colors.RED}❌ Unknown command: {command}{Colors.END}")
|
|
251
250
|
print(f"{Colors.YELLOW}💡 Type 'help' for available commands.{Colors.END}")
|
|
251
|
+
|
|
252
252
|
except KeyboardInterrupt:
|
|
253
253
|
print(f"\n{Colors.CYAN}👋 Goodbye!{Colors.END}")
|
|
254
|
+
interactive_shell.already_running = False
|
|
254
255
|
break
|
|
256
|
+
except Exception as e:
|
|
257
|
+
print(f"{Colors.RED}❌ Error: {e}{Colors.END}")
|
|
258
|
+
|
|
259
|
+
interactive_shell.already_running = False
|
|
255
260
|
|
|
256
261
|
# ============ تابع اصلی (ورودی CLI) ============
|
|
257
262
|
def main():
|
|
258
263
|
command_name = os.path.basename(sys.argv[0])
|
|
259
264
|
args = sys.argv[1:]
|
|
260
265
|
|
|
261
|
-
# اگر دستور `pustil` (کوچک) باشه، به عنوان Pustil رفتار کن
|
|
262
|
-
if command_name.lower() == "pustil":
|
|
263
|
-
command_name = "Pustil"
|
|
264
|
-
|
|
265
|
-
# نمایش لوگو (اختیاری)
|
|
266
|
-
# print_logo(command_name) # میتونی لوگو رو هم اضافه کنی
|
|
267
|
-
|
|
268
|
-
# پردازش آرگومانها
|
|
269
266
|
if "--help" in args or "-h" in args:
|
|
270
|
-
show_help(
|
|
267
|
+
show_help()
|
|
271
268
|
return
|
|
272
269
|
if "--version" in args or "-v" in args:
|
|
273
270
|
show_version()
|
|
274
271
|
return
|
|
275
272
|
|
|
276
|
-
# اگر آرگومانی نباشه => شل
|
|
273
|
+
# اگر هیچ آرگومانی نباشه => لاگین کن و شل باز کن
|
|
277
274
|
if len(args) == 0:
|
|
278
|
-
# ابتدا لاگین میکنیم
|
|
279
275
|
if not SESSION.get('logged_in'):
|
|
280
276
|
if not cmd_login():
|
|
281
277
|
return
|
|
282
|
-
interactive_shell()
|
|
278
|
+
interactive_shell(first_run=True)
|
|
283
279
|
return
|
|
284
280
|
|
|
285
|
-
# پردازش دستورات تکخطی
|
|
281
|
+
# پردازش دستورات تکخطی
|
|
286
282
|
subcommand = args[0].lower()
|
|
287
283
|
rest_args = args[1:]
|
|
288
284
|
|
|
@@ -295,7 +291,10 @@ def main():
|
|
|
295
291
|
elif subcommand == "set" and len(rest_args) >= 1 and rest_args[0] == "owner":
|
|
296
292
|
cmd_set_owner()
|
|
297
293
|
elif subcommand == "search" and len(rest_args) >= 2 and rest_args[0] == "usr":
|
|
298
|
-
|
|
294
|
+
filename = " ".join(rest_args[1:])
|
|
295
|
+
cmd_search(filename)
|
|
296
|
+
elif subcommand == "msg":
|
|
297
|
+
cmd_msg()
|
|
299
298
|
elif subcommand == "shell":
|
|
300
299
|
if not SESSION.get('logged_in'):
|
|
301
300
|
if not cmd_login():
|
|
@@ -305,36 +304,36 @@ def main():
|
|
|
305
304
|
print(f"{Colors.RED}❌ Unknown command: {subcommand}{Colors.END}")
|
|
306
305
|
print(f"{Colors.YELLOW}💡 Try: pustil --help{Colors.END}")
|
|
307
306
|
|
|
308
|
-
def show_help(
|
|
307
|
+
def show_help():
|
|
309
308
|
print(f"{Colors.BOLD}{Colors.CYAN}📖 pStar CLI Help{Colors.END}")
|
|
310
|
-
print(f"{Colors.YELLOW}Usage:{Colors.END}
|
|
309
|
+
print(f"{Colors.YELLOW}Usage:{Colors.END} pustil [COMMAND] [OPTIONS]")
|
|
311
310
|
print()
|
|
312
311
|
print(f"{Colors.GREEN}Commands:{Colors.END}")
|
|
313
|
-
print(" login - Login with animation
|
|
312
|
+
print(" login - Login with animation")
|
|
314
313
|
print(" logout - Logout")
|
|
315
|
-
print(" status - Show
|
|
316
|
-
print(" set owner - Verify owner password
|
|
317
|
-
print(" search usr <file> - Search user TXT file
|
|
314
|
+
print(" status - Show login status")
|
|
315
|
+
print(" set owner - Verify owner password")
|
|
316
|
+
print(" search usr <file> - Search user TXT file")
|
|
317
|
+
print(" msg - Message feature (coming soon)")
|
|
318
318
|
print(" shell - Enter interactive shell (✯>)")
|
|
319
319
|
print(" --help, -h - Show this help")
|
|
320
320
|
print(" --version, -v - Show version")
|
|
321
321
|
print()
|
|
322
322
|
print(f"{Colors.YELLOW}Examples:{Colors.END}")
|
|
323
|
-
print(
|
|
324
|
-
print(
|
|
325
|
-
print(
|
|
326
|
-
print(
|
|
323
|
+
print(" pustil login")
|
|
324
|
+
print(" pustil set owner")
|
|
325
|
+
print(" pustil search usr sample.txt")
|
|
326
|
+
print(" pustil shell")
|
|
327
327
|
|
|
328
328
|
def show_version():
|
|
329
329
|
print(f"{Colors.BOLD}{Colors.GREEN}pStar CLI v{VERSION}{Colors.END}")
|
|
330
330
|
print(f"{Colors.CYAN}Released: 2026-06-27{Colors.END}")
|
|
331
|
-
print(f"{Colors.YELLOW}✨ Built with ❤️ in Termux{Colors.END}")
|
|
332
331
|
|
|
333
332
|
if __name__ == "__main__":
|
|
334
333
|
try:
|
|
335
334
|
main()
|
|
336
335
|
except KeyboardInterrupt:
|
|
337
|
-
print(f"\n{Colors.YELLOW}⚠️ Interrupted
|
|
336
|
+
print(f"\n{Colors.YELLOW}⚠️ Interrupted. Goodbye!{Colors.END}")
|
|
338
337
|
sys.exit(0)
|
|
339
338
|
except Exception as e:
|
|
340
339
|
print(f"{Colors.RED}❌ Error: {e}{Colors.END}")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|