sharkit 0.2.0.dev2__tar.gz → 0.2.1__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.
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/PKG-INFO +1 -1
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/pyproject.toml +1 -1
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/app.py +2 -2
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/commands/builtins.py +95 -22
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/output/renderer.py +4 -1
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/tools/manager.py +15 -1
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/tools/osint/recon/hybrid/blackbird.py +3 -1
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/tools/osint/recon/username/maigret.py +1 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/tools/osint/recon/username/sherlock.py +1 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/.gitignore +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/LICENSE +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/README.md +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/__init__.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/__main__.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/commands/__init__.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/commands/base.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/commands/registry.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/config/__init__.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/config/manager.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/config/paths.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/console/__init__.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/console/completion.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/console/prompt.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/console/repl.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/exceptions.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/history/__init__.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/history/manager.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/network/__init__.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/network/client.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/output/__init__.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/output/theme.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/tools/__init__.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/tools/base.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/tools/loader.py +0 -0
- {sharkit-0.2.0.dev2 → sharkit-0.2.1}/src/sharkit/tools/registry.py +0 -0
|
@@ -20,7 +20,7 @@ NON_LINUX_MESSAGE = (
|
|
|
20
20
|
"it was built for open water,\n"
|
|
21
21
|
"where it can actually swim.\n"
|
|
22
22
|
"\n"
|
|
23
|
-
"windows
|
|
23
|
+
"windows is more of a glass aquarium.\n"
|
|
24
24
|
"tidy, bright, and a little too enclosed.\n"
|
|
25
25
|
"\n"
|
|
26
26
|
"the shark doesn't dislike the aquarium.\n"
|
|
@@ -37,7 +37,7 @@ def main() -> int:
|
|
|
37
37
|
sys.stdout.flush()
|
|
38
38
|
renderer = Renderer()
|
|
39
39
|
|
|
40
|
-
if sys.platform
|
|
40
|
+
if sys.platform == "win32":
|
|
41
41
|
renderer.banner(tool_count=0, message=NON_LINUX_MESSAGE)
|
|
42
42
|
return 1
|
|
43
43
|
|
|
@@ -193,10 +193,16 @@ class UseCommand(Command):
|
|
|
193
193
|
self._log(context, f'Tool "{name}" is not installed. Run: install {name}')
|
|
194
194
|
return None
|
|
195
195
|
renderer = context.session.get("renderer")
|
|
196
|
+
first_progress = [True]
|
|
196
197
|
|
|
197
198
|
def on_progress(msg: str) -> None:
|
|
198
199
|
if renderer is not None:
|
|
199
|
-
|
|
200
|
+
tag = f"install {display}"
|
|
201
|
+
if first_progress[0]:
|
|
202
|
+
renderer.gutter(tag, msg, GREEN, is_first=True)
|
|
203
|
+
first_progress[0] = False
|
|
204
|
+
else:
|
|
205
|
+
renderer.gutter(tag, msg, GREEN, is_first=False)
|
|
200
206
|
|
|
201
207
|
ok, message = tool_manager.install(name, spec, on_progress=on_progress)
|
|
202
208
|
if not ok:
|
|
@@ -382,7 +388,13 @@ class SetCommand(Command):
|
|
|
382
388
|
tool_instance.set_option(key, value)
|
|
383
389
|
renderer = context.session.get("renderer")
|
|
384
390
|
if renderer is not None:
|
|
385
|
-
|
|
391
|
+
tool_registry = context.session.get("tool_registry")
|
|
392
|
+
display = context.current_tool
|
|
393
|
+
if tool_registry is not None and context.current_tool is not None:
|
|
394
|
+
display = tool_registry.format_display(
|
|
395
|
+
tool_registry.get_tool_path(context.current_tool),
|
|
396
|
+
)
|
|
397
|
+
renderer.log_line(f"set {display}", f"{key} = {value}")
|
|
386
398
|
return None
|
|
387
399
|
return f"Set {key} = {value}"
|
|
388
400
|
except Exception as e:
|
|
@@ -627,24 +639,44 @@ class InstallCommand(Command):
|
|
|
627
639
|
tool_cls = tool_registry.get_tool(name)
|
|
628
640
|
if tool_cls is None or tool_cls.metadata.install is None:
|
|
629
641
|
return f'Tool "{name}" is not an external tool or was not found.'
|
|
630
|
-
|
|
631
|
-
|
|
642
|
+
tool_name = tool_cls.metadata.name
|
|
643
|
+
display = tool_registry.format_display(tool_registry.get_tool_path(tool_name))
|
|
644
|
+
if tool_manager.is_installed(tool_name):
|
|
632
645
|
renderer = context.session.get("renderer")
|
|
633
646
|
if renderer is not None:
|
|
634
647
|
renderer.log_line(f"install {display}", "already installed", color=GREEN)
|
|
635
648
|
return None
|
|
636
649
|
renderer = context.session.get("renderer")
|
|
650
|
+
first_progress = [True]
|
|
637
651
|
|
|
638
652
|
def on_progress(msg: str) -> None:
|
|
639
653
|
if renderer is not None:
|
|
640
|
-
|
|
654
|
+
tag = f"install {display}"
|
|
655
|
+
if first_progress[0]:
|
|
656
|
+
renderer.gutter(tag, msg, GREEN, is_first=True)
|
|
657
|
+
first_progress[0] = False
|
|
658
|
+
else:
|
|
659
|
+
renderer.gutter(tag, msg, GREEN, is_first=False)
|
|
641
660
|
|
|
642
|
-
|
|
661
|
+
install_spec = tool_cls.metadata.install
|
|
662
|
+
ok, message = tool_manager.install(
|
|
663
|
+
tool_name, install_spec, on_progress=on_progress
|
|
664
|
+
)
|
|
643
665
|
if renderer is not None:
|
|
666
|
+
tag = f"install {display}"
|
|
644
667
|
if ok:
|
|
645
|
-
|
|
668
|
+
msg = "installed"
|
|
669
|
+
elif message == "Aborted":
|
|
670
|
+
msg = "aborted"
|
|
671
|
+
print("\r\033[K", end="")
|
|
646
672
|
else:
|
|
647
|
-
|
|
673
|
+
msg = f"failed: {message}"
|
|
674
|
+
if first_progress[0]:
|
|
675
|
+
renderer.log_line(tag, msg, color=GREEN)
|
|
676
|
+
else:
|
|
677
|
+
lines = msg.splitlines() or [""]
|
|
678
|
+
for line in lines:
|
|
679
|
+
renderer.gutter(tag, line, GREEN, is_first=False)
|
|
648
680
|
return None
|
|
649
681
|
return str(message)
|
|
650
682
|
|
|
@@ -671,24 +703,44 @@ class UpgradeCommand(Command):
|
|
|
671
703
|
tool_cls = tool_registry.get_tool(name)
|
|
672
704
|
if tool_cls is None or tool_cls.metadata.install is None:
|
|
673
705
|
return f'Tool "{name}" is not an external tool or was not found.'
|
|
674
|
-
|
|
675
|
-
|
|
706
|
+
tool_name = tool_cls.metadata.name
|
|
707
|
+
display = tool_registry.format_display(tool_registry.get_tool_path(tool_name))
|
|
708
|
+
if not tool_manager.is_installed(tool_name):
|
|
676
709
|
renderer = context.session.get("renderer")
|
|
677
710
|
if renderer is not None:
|
|
678
711
|
renderer.log_line(f"upgrade {display}", "not installed (skipped)", color=BLUE)
|
|
679
712
|
return None
|
|
680
713
|
renderer = context.session.get("renderer")
|
|
714
|
+
first_progress = [True]
|
|
681
715
|
|
|
682
716
|
def on_progress(msg: str) -> None:
|
|
683
717
|
if renderer is not None:
|
|
684
|
-
|
|
718
|
+
tag = f"upgrade {display}"
|
|
719
|
+
if first_progress[0]:
|
|
720
|
+
renderer.gutter(tag, msg, BLUE, is_first=True)
|
|
721
|
+
first_progress[0] = False
|
|
722
|
+
else:
|
|
723
|
+
renderer.gutter(tag, msg, BLUE, is_first=False)
|
|
685
724
|
|
|
686
|
-
|
|
725
|
+
upgrade_spec = tool_cls.metadata.install
|
|
726
|
+
ok, message = tool_manager.update(
|
|
727
|
+
tool_name, upgrade_spec, on_progress=on_progress
|
|
728
|
+
)
|
|
687
729
|
if renderer is not None:
|
|
730
|
+
tag = f"upgrade {display}"
|
|
688
731
|
if ok:
|
|
689
|
-
|
|
732
|
+
msg = "upgraded"
|
|
733
|
+
elif message == "Aborted":
|
|
734
|
+
msg = "aborted"
|
|
735
|
+
print("\r\033[K", end="")
|
|
690
736
|
else:
|
|
691
|
-
|
|
737
|
+
msg = f"failed: {message}"
|
|
738
|
+
if first_progress[0]:
|
|
739
|
+
renderer.log_line(tag, msg, color=BLUE)
|
|
740
|
+
else:
|
|
741
|
+
lines = msg.splitlines() or [""]
|
|
742
|
+
for line in lines:
|
|
743
|
+
renderer.gutter(tag, line, BLUE, is_first=False)
|
|
692
744
|
return None
|
|
693
745
|
return str(message)
|
|
694
746
|
|
|
@@ -721,17 +773,37 @@ class UpgradeCommand(Command):
|
|
|
721
773
|
renderer.log_line(f"upgrade {display}", "not installed (skipped)", color=BLUE)
|
|
722
774
|
continue
|
|
723
775
|
renderer = context.session.get("renderer")
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
776
|
+
first_progress = [True]
|
|
777
|
+
|
|
778
|
+
def on_progress(
|
|
779
|
+
msg: str,
|
|
780
|
+
_first: list[bool] = first_progress,
|
|
781
|
+
_tag: str = f"upgrade {display}",
|
|
782
|
+
_renderer: Any = renderer,
|
|
783
|
+
) -> None:
|
|
784
|
+
if _renderer is not None:
|
|
785
|
+
if _first[0]:
|
|
786
|
+
_renderer.gutter(_tag, msg, BLUE, is_first=True)
|
|
787
|
+
_first[0] = False
|
|
788
|
+
else:
|
|
789
|
+
_renderer.gutter(_tag, msg, BLUE, is_first=False)
|
|
728
790
|
|
|
729
791
|
ok, message = tool_manager.update(name, spec, on_progress=on_progress)
|
|
730
792
|
if renderer is not None:
|
|
793
|
+
tag = f"upgrade {display}"
|
|
731
794
|
if ok:
|
|
732
|
-
|
|
795
|
+
msg = "upgraded"
|
|
796
|
+
elif message == "Aborted":
|
|
797
|
+
msg = "aborted"
|
|
798
|
+
print("\r\033[K", end="")
|
|
799
|
+
else:
|
|
800
|
+
msg = f"failed: {message}"
|
|
801
|
+
if first_progress[0]:
|
|
802
|
+
renderer.log_line(tag, msg, color=BLUE)
|
|
733
803
|
else:
|
|
734
|
-
|
|
804
|
+
lines = msg.splitlines() or [""]
|
|
805
|
+
for line in lines:
|
|
806
|
+
renderer.gutter(tag, line, BLUE, is_first=False)
|
|
735
807
|
return None
|
|
736
808
|
|
|
737
809
|
|
|
@@ -753,9 +825,10 @@ class RemoveCommand(Command):
|
|
|
753
825
|
tool_cls = tool_registry.get_tool(name)
|
|
754
826
|
if tool_cls is None or tool_cls.metadata.install is None:
|
|
755
827
|
return f'Tool "{name}" is not an external tool or was not found.'
|
|
756
|
-
|
|
828
|
+
tool_name = tool_cls.metadata.name
|
|
829
|
+
display = tool_registry.format_display(tool_registry.get_tool_path(tool_name))
|
|
757
830
|
renderer = context.session.get("renderer")
|
|
758
|
-
ok, message = tool_manager.uninstall(
|
|
831
|
+
ok, message = tool_manager.uninstall(tool_name)
|
|
759
832
|
if renderer is not None:
|
|
760
833
|
if ok:
|
|
761
834
|
renderer.log_line(f"remove {display}", "removed", color=RED)
|
|
@@ -253,7 +253,10 @@ class Renderer:
|
|
|
253
253
|
print(text, end="")
|
|
254
254
|
|
|
255
255
|
def log_line(self, tag: str, message: str, color: str = PINK) -> None:
|
|
256
|
-
|
|
256
|
+
lines = message.splitlines() or [""]
|
|
257
|
+
self.gutter(tag, lines[0], color, is_first=True)
|
|
258
|
+
for line in lines[1:]:
|
|
259
|
+
print(f"{color}{BOLD}│{RESET} {line}")
|
|
257
260
|
|
|
258
261
|
def gutter(self, name: str, line: str, color: str, is_first: bool) -> None:
|
|
259
262
|
if is_first:
|
|
@@ -54,7 +54,11 @@ class ToolManager:
|
|
|
54
54
|
self._run([pip, "install", *spec.pip_args])
|
|
55
55
|
dest.joinpath(".installed").write_text(name)
|
|
56
56
|
return True, f'Tool "{name}" installed.'
|
|
57
|
+
except KeyboardInterrupt:
|
|
58
|
+
shutil.rmtree(dest, ignore_errors=True)
|
|
59
|
+
return False, "Aborted"
|
|
57
60
|
except Exception as e:
|
|
61
|
+
shutil.rmtree(dest, ignore_errors=True)
|
|
58
62
|
return False, f'Failed to install "{name}": {e}'
|
|
59
63
|
|
|
60
64
|
def update(
|
|
@@ -82,6 +86,8 @@ class ToolManager:
|
|
|
82
86
|
on_progress("upgrading packages...")
|
|
83
87
|
self._run([pip, "install", "--upgrade", *spec.pip_args])
|
|
84
88
|
return True, f'Tool "{name}" updated.'
|
|
89
|
+
except KeyboardInterrupt:
|
|
90
|
+
return False, "Aborted"
|
|
85
91
|
except Exception as e:
|
|
86
92
|
return False, f'Failed to update "{name}": {e}'
|
|
87
93
|
|
|
@@ -96,4 +102,12 @@ class ToolManager:
|
|
|
96
102
|
return False, f'Failed to uninstall "{name}": {e}'
|
|
97
103
|
|
|
98
104
|
def _run(self, cmd: list[str]) -> None:
|
|
99
|
-
subprocess.run(cmd,
|
|
105
|
+
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
106
|
+
if result.returncode != 0:
|
|
107
|
+
stderr = result.stderr.strip() if result.stderr else ""
|
|
108
|
+
stdout = result.stdout.strip() if result.stdout else ""
|
|
109
|
+
raw = stderr or stdout or "No output"
|
|
110
|
+
# Truncate long build output — keep last 20 lines where the actual error lives
|
|
111
|
+
lines = raw.splitlines()
|
|
112
|
+
detail = "\n".join(lines[-20:]) if len(lines) > 20 else raw
|
|
113
|
+
raise RuntimeError(detail)
|
|
@@ -107,7 +107,7 @@ class BlackbirdTool(Tool):
|
|
|
107
107
|
success=False,
|
|
108
108
|
error="Both 'type' and 'query' options are required.",
|
|
109
109
|
)
|
|
110
|
-
args = [f"--{stype}", query
|
|
110
|
+
args = [f"--{stype}", query]
|
|
111
111
|
if parse_bool(context.options.get("pdf")):
|
|
112
112
|
args.append("--pdf")
|
|
113
113
|
renderer = context.renderer
|
|
@@ -191,6 +191,8 @@ class BlackbirdTool(Tool):
|
|
|
191
191
|
proc.kill()
|
|
192
192
|
current = ""
|
|
193
193
|
if renderer is not None:
|
|
194
|
+
# \r\033[K clears the ^C echo from the terminal before printing.
|
|
195
|
+
print("\r\033[K", end="")
|
|
194
196
|
renderer.gutter(name, "Run aborted (Ctrl+C).", tool_color, first)
|
|
195
197
|
else:
|
|
196
198
|
print("Run aborted (Ctrl+C).")
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|