Search and info
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
# 🎠horsy [](https://horsy.ml/)
|
# [🎠horsy](https://horsy.ml/) [](https://horsy.ml/)
|
||||||
|
|
||||||
## _The Best Open Source Package Manager_
|
## _The Best Open Source Package Manager_
|
||||||
|
|
||||||
horsy in Python-powered multi launcher and app installer
|
horsy in Python-powered multi launcher and app installer
|
||||||
@@ -7,5 +8,8 @@ horsy in Python-powered multi launcher and app installer
|
|||||||
- 🎛️CLI and custom very simple Text UI
|
- 🎛️CLI and custom very simple Text UI
|
||||||
- 🖼️GUI (development)
|
- 🖼️GUI (development)
|
||||||
- ✨VirusTotal Magic
|
- ✨VirusTotal Magic
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
Project in development, you will see something interesting soon 🤖
|
Project in development, you will see something interesting soon 🤖
|
||||||
17
horsy.py
17
horsy.py
@@ -8,14 +8,15 @@ from modules.manager import install, uninstall
|
|||||||
from modules.virustotal import add_to_cfg
|
from modules.virustotal import add_to_cfg
|
||||||
from modules.uploader import upload
|
from modules.uploader import upload
|
||||||
from modules.source import get_source
|
from modules.source import get_source
|
||||||
|
from modules.search import search, info
|
||||||
import modules.vars as horsy_vars
|
import modules.vars as horsy_vars
|
||||||
|
|
||||||
# Getting the arguments
|
# Getting the arguments
|
||||||
parser = argparse.ArgumentParser(description='horsy - the best package manager')
|
parser = argparse.ArgumentParser(description='horsy - the best package manager')
|
||||||
parser.add_argument('option', help='options for horsy (install/i | uninstall/un | source/s | update/u | list/l | '
|
parser.add_argument('option', help='options for horsy (install/i | uninstall/un | source/s | update/u | list/l | '
|
||||||
'upload)',
|
'upload | search | info)',
|
||||||
choices=['install', 'i', 'uninstall', 'un', 'source', 's', 'update', 'u', 'list', 'l', 'upload',
|
choices=['install', 'i', 'uninstall', 'un', 'source', 's', 'update', 'u', 'list', 'l', 'upload',
|
||||||
'search'],
|
'search', 'info'],
|
||||||
nargs='?')
|
nargs='?')
|
||||||
parser.add_argument('app', help='app to install/uninstall/download source', nargs='?')
|
parser.add_argument('app', help='app to install/uninstall/download source', nargs='?')
|
||||||
parser.add_argument('--vt', help='your virustotal api key (account -> api key in VT)', dest='vt_key')
|
parser.add_argument('--vt', help='your virustotal api key (account -> api key in VT)', dest='vt_key')
|
||||||
@@ -58,13 +59,13 @@ if args.vt_key:
|
|||||||
|
|
||||||
# Checking if arguments are empty to use in-app CLI
|
# Checking if arguments are empty to use in-app CLI
|
||||||
if not args.option:
|
if not args.option:
|
||||||
option = ['install', 'uninstall', 'source', 'update', 'list', 'upload', 'search'][
|
option = ['install', 'uninstall', 'source', 'update', 'list', 'upload', 'search', 'info'][
|
||||||
tui.menu(['install app', 'uninstall app', 'get source', 'update app', 'list of installed apps',
|
tui.menu(['install app', 'uninstall app', 'get source', 'update app', 'list of installed apps',
|
||||||
'upload your app', 'search for app'])]
|
'upload your app', 'search for app', 'get information about app'])]
|
||||||
isNoArgs = True
|
isNoArgs = True
|
||||||
|
|
||||||
if not args.app:
|
if not args.app:
|
||||||
if option not in ['list', 'upload']:
|
if option not in ['list', 'upload', 'update']:
|
||||||
print('\n')
|
print('\n')
|
||||||
app = tui.get(f'Select app to {option}')
|
app = tui.get(f'Select app to {option}')
|
||||||
|
|
||||||
@@ -80,5 +81,11 @@ if option in ['uninstall', 'un']:
|
|||||||
if option in ['source', 's']:
|
if option in ['source', 's']:
|
||||||
get_source(app)
|
get_source(app)
|
||||||
|
|
||||||
|
if option in ['search']:
|
||||||
|
search(app)
|
||||||
|
|
||||||
|
if option in ['info']:
|
||||||
|
info(app)
|
||||||
|
|
||||||
if isNoArgs:
|
if isNoArgs:
|
||||||
input('[EXIT] Press enter to exit horsy...')
|
input('[EXIT] Press enter to exit horsy...')
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ from modules.virustotal import get_key, scan_file, get_report
|
|||||||
|
|
||||||
def install(package, is_gui=False):
|
def install(package, is_gui=False):
|
||||||
r = requests.get(f"{horsy_vars.protocol}{horsy_vars.server_url}/packages/json/{package}").text
|
r = requests.get(f"{horsy_vars.protocol}{horsy_vars.server_url}/packages/json/{package}").text
|
||||||
|
if r == "":
|
||||||
|
print(f"[red]Package {package} not found[/]")
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
r = json.loads(r)
|
r = json.loads(r)
|
||||||
except:
|
except:
|
||||||
print("[red]Error with unsupported message[/]")
|
print("[red]Error with unsupported message[/]")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
if r["message"] == "not found":
|
|
||||||
print("[red]Package not found[/]")
|
|
||||||
return
|
|
||||||
if r["message"] == "Internal server error":
|
if r["message"] == "Internal server error":
|
||||||
print("[red]Internal server error[/]")
|
print("[red]Internal server error[/]")
|
||||||
return
|
return
|
||||||
@@ -55,7 +55,8 @@ def install(package, is_gui=False):
|
|||||||
f"[italic white] in terminal[/]")
|
f"[italic white] in terminal[/]")
|
||||||
scan_file('{2}apps/{0}/{1}'.format(r['name'], r['url'].split('/')[-1], horsy_vars.horsypath))
|
scan_file('{2}apps/{0}/{1}'.format(r['name'], r['url'].split('/')[-1], horsy_vars.horsypath))
|
||||||
print(f"[green]Virustotal scan finished[/]")
|
print(f"[green]Virustotal scan finished[/]")
|
||||||
analysis = get_report('{2}apps/{0}/{1}'.format(r['name'], r['url'].split('/')[-1], horsy_vars.horsypath))
|
analysis = get_report('{2}apps/{0}/{1}'.format(r['name'], r['url'].split('/')[-1],
|
||||||
|
horsy_vars.horsypath))
|
||||||
print(f"[green]You can see report by opening: [white]{analysis['link']}[/]")
|
print(f"[green]You can see report by opening: [white]{analysis['link']}[/]")
|
||||||
print(f"{analysis['detect']['malicious']} antivirus flagged this file as malicious")
|
print(f"{analysis['detect']['malicious']} antivirus flagged this file as malicious")
|
||||||
|
|
||||||
@@ -78,8 +79,8 @@ def install(package, is_gui=False):
|
|||||||
|
|
||||||
chunk_size = 1024
|
chunk_size = 1024
|
||||||
file_r = requests.get(r['download'], stream=True)
|
file_r = requests.get(r['download'], stream=True)
|
||||||
with open('{2}apps/{0}/{1}'.format(r['name'], r['download'].split('/')[-1], horsy_vars.horsypath), "wb") \
|
with open('{2}apps/{0}/{1}'.format(r['name'], r['download'].split('/')[-1], horsy_vars.horsypath),
|
||||||
as f:
|
"wb") as f:
|
||||||
pbar = tqdm(unit="B", unit_scale=True, total=int(file_r.headers['Content-Length']))
|
pbar = tqdm(unit="B", unit_scale=True, total=int(file_r.headers['Content-Length']))
|
||||||
for chunk in file_r.iter_content(chunk_size=chunk_size):
|
for chunk in file_r.iter_content(chunk_size=chunk_size):
|
||||||
if chunk:
|
if chunk:
|
||||||
@@ -120,7 +121,7 @@ def install(package, is_gui=False):
|
|||||||
|
|
||||||
except:
|
except:
|
||||||
print("[red]Unexpected error[/]")
|
print("[red]Unexpected error[/]")
|
||||||
raise
|
# raise
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
49
modules/search.py
Normal file
49
modules/search.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import textwrap
|
||||||
|
from algoliasearch.search_client import SearchClient
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import modules.vars as horsy_vars
|
||||||
|
import json
|
||||||
|
from rich import print
|
||||||
|
|
||||||
|
|
||||||
|
client = SearchClient.create('VBUJO9OW62', '759f6c7986842fd8218e79e3b9ddb964')
|
||||||
|
index = client.init_index('packages')
|
||||||
|
|
||||||
|
|
||||||
|
def search(query):
|
||||||
|
res = index.search(query)['hits']
|
||||||
|
for i in res:
|
||||||
|
print(textwrap.shorten(f"{i['name']} by {i['authorName']} - {i['description']}",
|
||||||
|
width=os.get_terminal_size().columns))
|
||||||
|
|
||||||
|
|
||||||
|
def info(package):
|
||||||
|
r = requests.get(f"{horsy_vars.protocol}{horsy_vars.server_url}/packages/json/{package}").text
|
||||||
|
if r == "":
|
||||||
|
print(f"[red]Package {package} not found[/]")
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
r = json.loads(r)
|
||||||
|
except:
|
||||||
|
print("[red]Error with unsupported message[/]")
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
if r["message"] == "Internal server error":
|
||||||
|
print("[red]Internal server error[/]")
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
print(f"[bold]{r['name']}{'✅' if r['verified'] else ''} by {r['authorName']}[/]")
|
||||||
|
print(f"{r['description']}")
|
||||||
|
print(f"👍{r['likes']} | 👎{r['dislikes']}")
|
||||||
|
if not r['verified']:
|
||||||
|
print("This package is not verified by the horsy team. This means that it \n"
|
||||||
|
"can be unstable or it can be malware. Most packages have unverified\n"
|
||||||
|
"state, but use it at your own risk.")
|
||||||
|
else:
|
||||||
|
print("This package is [green]verified[/] by the horsy team! \n"
|
||||||
|
"Keep in mind, developers can change the code after verification \n"
|
||||||
|
"We [red]don't call you to trust this app[/], use it at your own risk \n"
|
||||||
|
"but we recommend you more to install verified packages")
|
||||||
@@ -2,4 +2,5 @@ rich
|
|||||||
requests
|
requests
|
||||||
Cryptography
|
Cryptography
|
||||||
Pyinstaller
|
Pyinstaller
|
||||||
tqdm
|
tqdm
|
||||||
|
algoliasearch
|
||||||
Reference in New Issue
Block a user