Compare commits

..

19 Commits

Author SHA1 Message Date
Richard Mwewa
d7980c0726 Delete tmp 2022-04-23 13:33:01 +02:00
Richard Mwewa
f8221d8f58 Update main.py 2022-04-23 13:32:25 +02:00
Richard Mwewa
9d86c4cc7b Update README.md 2022-04-23 13:25:30 +02:00
Richard Mwewa
67db855322 Update banner.py 2022-04-23 13:18:28 +02:00
Richard Mwewa
1b5cfa2ebf Update colors.py 2022-04-23 13:17:37 +02:00
Richard Mwewa
0d2a939388 Update main.py 2022-04-23 13:16:04 +02:00
Richard Mwewa
52c572f255 Update README.md 2022-04-20 00:40:38 +02:00
Richard Mwewa
eeda47723e Update main.py 2022-04-20 00:32:49 +02:00
Richard Mwewa
1a6e3bb3c9 Update banner.py 2022-04-20 00:28:49 +02:00
Richard Mwewa
82b6a3fd3c Update colors.py 2022-04-20 00:27:55 +02:00
Richard Mwewa
c994678fa1 Update README.md 2022-04-18 14:19:37 +02:00
Richard Mwewa
9ef14f3e4f Update octosuite 2022-04-14 11:19:34 +02:00
Richard Mwewa
23270e8da9 Update octosuite 2022-04-14 11:15:18 +02:00
Richard Mwewa
619070348b Update banner.py 2022-04-14 11:13:01 +02:00
Richard Mwewa
5718c5f229 Update colors.py 2022-04-14 11:11:41 +02:00
Richard Mwewa
b4f009c7d4 Update main.py 2022-04-14 11:09:43 +02:00
Richard Mwewa
82a95d84b0 Update README.md 2022-04-14 11:07:42 +02:00
Richard Mwewa
425525bf94 Update README.md 2022-04-14 00:57:55 +02:00
Richard Mwewa
24c6b54d19 Update main.py 2022-04-11 13:13:57 +02:00
6 changed files with 262 additions and 188 deletions

View File

@@ -1 +0,0 @@

View File

@@ -1,12 +1,10 @@
![Screenshot_2022-03-17_10-12-53](https://user-images.githubusercontent.com/74001397/158868105-b5aba7e8-7342-4268-bd7a-6d6ae0bdae5a.png)
![OS](https://img.shields.io/badge/OS-GNU%2FLinux-red?style=for-the-badge&logo=Linux) ![OS](https://img.shields.io/badge/OS-GNU%2FLinux-red?style=for-the-badge&logo=Linux)
![OS](https://img.shields.io/badge/OS-Windows-blue?style=for-the-badge&logo=Windows) ![OS](https://img.shields.io/badge/OS-Windows-blue?style=for-the-badge&logo=Windows)
![OS](https://img.shields.io/badge/OS-Mac-white?style=for-the-badge&logo=apple) ![OS](https://img.shields.io/badge/OS-Mac-white?style=for-the-badge&logo=apple)
![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/rly0nheart/octosuite?style=for-the-badge&logo=github)
![GitHub commits since latest release (by date)](https://img.shields.io/github/commits-since/rly0nheart/octosuite/1.5.1-beta?style=for-the-badge&logo=github)
![GitHub last commit](https://img.shields.io/github/last-commit/rly0nheart/octosuite?style=for-the-badge&logo=github)
![GitHub](https://img.shields.io/github/license/rly0nheart/octosuite?style=for-the-badge&logo=github) ![GitHub](https://img.shields.io/github/license/rly0nheart/octosuite?style=for-the-badge&logo=github)
![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/rly0nheart/octosuite?style=for-the-badge&logo=github)
![GitHub commits since latest release (by date)](https://img.shields.io/github/commits-since/rly0nheart/octosuite/1.7.0-dev?style=for-the-badge&logo=github)
![GitHub last commit](https://img.shields.io/github/last-commit/rly0nheart/octosuite?style=for-the-badge&logo=github)
![GitHub repo size](https://img.shields.io/github/repo-size/rly0nheart/octosuite?style=for-the-badge&logo=github) ![GitHub repo size](https://img.shields.io/github/repo-size/rly0nheart/octosuite?style=for-the-badge&logo=github)
> *Simply gather OSINT on Github users & organizations like a God🔥* > *Simply gather OSINT on Github users & organizations like a God🔥*
@@ -28,6 +26,7 @@
- [x] Searches commits - [x] Searches commits
- [x] Easily updates with the 'update' command - [x] Easily updates with the 'update' command
- [x] Automatically logs network activity (.logs folder) - [x] Automatically logs network activity (.logs folder)
- [x] User can view, read and delete log files
# INSTALLATION # INSTALLATION
## Clone from Github ## Clone from Github
@@ -35,29 +34,44 @@
``` ```
git clone https://github.com/rly0nheart/octosuite.git git clone https://github.com/rly0nheart/octosuite.git
``` ```
![Screenshot_20220414-002508](https://user-images.githubusercontent.com/74001397/163280996-ed0f8817-c3e3-49d8-9e15-93452cb08a3e.jpg)
``` ```
cd octosuite cd octosuite
``` ```
![Screenshot_20220414-002214](https://user-images.githubusercontent.com/74001397/163281317-158bbf7b-073f-457e-8a8a-730d4c0ed413.jpg)
``` ```
pip install -r requirements.txt pip install -r requirements.txt
``` ```
![Screenshot_20220414-004420](https://user-images.githubusercontent.com/74001397/163282481-6cb5efe8-6e5a-4c2b-a8b5-7ff99f7ca293.jpg)
## Install from PyPI ## Install from PyPI
``` ```
pip install octosuite pip install octosuite
``` ```
![Screenshot_20220414-005400](https://user-images.githubusercontent.com/74001397/163283184-e9458439-8074-4338-938b-4588390bb6b7.jpg)
# GITHUB FORK USAGE # GITHUB FORK USAGE
## Linux ## Linux
``` ```
sudo chmod +x octosuite sudo chmod +x octosuite
``` ```
![Screenshot_20220414-004443](https://user-images.githubusercontent.com/74001397/163282620-a5307969-bcce-49d1-ad3c-c3ea0f78fb44.jpg)
``` ```
sudo ./octosuite sudo ./octosuite
``` ```
![Screenshot_20220414-004507](https://user-images.githubusercontent.com/74001397/163282716-41ace7fc-ee04-4c95-985e-68dd3286682c.jpg)
## Windows ## Windows
``` ```
@@ -86,25 +100,28 @@ octosuite
``` ```
# AVAILABLE COMMANDS # AVAILABLE COMMANDS
| Command | Usage| | COMMAND | DESCRIPTION|
| ------------- |:---------:| | ------------- |:---------:|
| ``orginfo`` | *get organization info* | | ``info:org`` | *get organization info* |
| ``userinfo`` | *get user profile info* | | ``info:user`` | *get user profile info* |
| ``repoinfo`` | *get repository info* | | ``info:repo`` | *get repository info* |
| ``pathcontents`` | *get contents of a path from a specified repository* | | ``info:dev`` | *show developer's info* |
| ``orgrepos`` | *get a list of repositories owned by a specified organization* | | ``path:contents`` | *get contents of a path from a specified repository* |
| ``userrepos`` | *get a list of repositories owned by a specified user* | | ``repos:org`` | *get a list of repositories owned by a specified organization* |
| ``usergists`` | *get a list of gists owned by a specified user* | | ``repos:user`` | *get a list of repositories owned by a specified user* |
| ``userfollowers`` | *get a list of a user's followers* | | ``user:gists`` | *get a list of gists owned by a specified user* |
| ``userfollowing`` | *check whether user A follows user B* | | ``user:followers`` | *get a list of a user's followers* |
| ``usersearch`` | *search user(s)* | | ``user:following`` | *check whether user A follows user B* |
| ``reposearch`` | *search repositor(y)(ies)* | | ``search:users`` | *search user(s)* |
| ``topicsearch`` | *search topics(s)* | | ``search:repos`` | *search repositor(y)(ies)* |
| ``issuesearch`` | *search issue(s)* | | ``search:topics`` | *search topics(s)* |
| ``commitsearch`` | *search commit(s)* | | ``search:issues`` | *search issue(s)* |
| ``search:commits`` | *search commit(s)* |
| ``logs:view`` | *view octosuite log files* |
| ``logs:read`` | *read a specified log file* |
| ``logs:delete`` | *delete a specified log file* |
| ``update`` | *update octosuite* | | ``update`` | *update octosuite* |
| ``changelog`` | *show changelog* | | ``changelog`` | *show changelog* |
| ``author`` | *show author info* |
| ``help`` | *show usage/help* | | ``help`` | *show usage/help* |
| ``exit`` | *exit session* | | ``exit`` | *exit session* |
@@ -112,12 +129,15 @@ octosuite
# NOTE # NOTE
* *octosuite automatically logs network and minor user activity. The logs are saved by date and time in .logs folder* * *octosuite automatically logs network and minor user activity. The logs are saved by date and time in .logs folder*
* *Although octosuite was developed to work on **Mac**, **Windows**, or any **Linux** *Distribution*, it has only been tested on **Termux** *and* **Kali Linux*** * *Although octosuite was developed to work on **Mac**, **Windows**, or any **Linux** *Distribution*, it has only been tested on **Termux** *and* **Kali Linux***
* *If you believe octosuite can be better, feel free to open a pull request with your improvements* ✌🏾🙂
# PYPI # PYPI
[PyPI](https://pypi.org/project/octosuite) [PyPI Package](https://pypi.org/project/octosuite)
![PyPI Downloads](https://pepy.tech/badge/octosuite)
# LICENSE # LICENSE
![license](https://user-images.githubusercontent.com/74001397/137917929-2f2cdb0c-4d1d-4e4b-9f0d-e01589e027b5.png) ![license](https://user-images.githubusercontent.com/74001397/137917929-2f2cdb0c-4d1d-4e4b-9f0d-e01589e027b5.png)
# ABOUT AUTHOR # ABOUT DEVELOPER
[About.me](https://about.me/rly0nheart) [About.me](https://about.me/rly0nheart)

View File

@@ -1,5 +1,5 @@
import os import os
from lib.colors import red,white,green,reset from lib.colors import red,white,white_bg,red_bg,reset
banner = f'''{red} banner = f'''{red}
▒█████ ▄████▄ ▄▄▄█████▓ ▒█████ ██████ █ ██ ██▓▄▄▄█████▓▓█████ ▒█████ ▄████▄ ▄▄▄█████▓ ▒█████ ██████ █ ██ ██▓▄▄▄█████▓▓█████
▒██▒ ██▒▒██▀ ▀█ ▓ ██▒ ▓▒▒██▒ ██▒▒██ ▒ ██ ▓██▒▓██▒▓ ██▒ ▓▒▓█ ▀ ▒██▒ ██▒▒██▀ ▀█ ▓ ██▒ ▓▒▒██▒ ██▒▒██ ▒ ██ ▓██▒▓██▒▓ ██▒ ▓▒▓█ ▀
@@ -8,15 +8,16 @@ banner = f'''{red}
░ ████▓▒░▒ ▓███▀ ░ ▒██▒ ░ ░ ████▓▒░▒██████▒▒▒█████▓ ░██░ ▒██▒ ░ ░▒████▒ ░ ████▓▒░▒ ▓███▀ ░ ▒██▒ ░ ░ ████▓▒░▒██████▒▒▒█████▓ ░██░ ▒██▒ ░ ░▒████▒
░ ▒░▒░▒░ ░ ░▒ ▒ ░ ▒ ░░ ░ ▒░▒░▒░ ▒ ▒▓▒ ▒ ░░▒▓▒ ▒ ▒ ░▓ ▒ ░░ ░░ ▒░ ░ ░ ▒░▒░▒░ ░ ░▒ ▒ ░ ▒ ░░ ░ ▒░▒░▒░ ▒ ▒▓▒ ▒ ░░▒▓▒ ▒ ▒ ░▓ ▒ ░░ ░░ ▒░ ░
░ ▒ ▒░ ░ ▒ ░ ░ ▒ ▒░ ░ ░▒ ░ ░░░▒░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ▒ ▒░ ░ ▒ ░ ░ ▒ ▒░ ░ ░▒ ░ ░░░▒░ ░ ░ ▒ ░ ░ ░ ░ ░
░ ░ ░ ▒ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░░░ ░ ░ ▒ v1.5.1-beta ░ ░ ░ ▒ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░░░ ░ ░ ▒ {red_bg}v1.7.0-dev{reset}{red}
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
{white}— Advanced Github {red}OSINT{white} Framework{reset} {white}— Advanced Github {red}OSINT{white} Framework{reset}
> {white}Welcome {os.getlogin()}{reset} > {white}Current user: {white_bg}{os.getlogin()}{reset}
> {white}use '{green}help{white}' command for usage{reset} > {white}Use {white_bg}help{reset}{white} command for usage{reset}
> {white}commands are case sensitive > {white}Commands are {white_bg}case sensitive{reset}
{'-'*30} {'-'*30}
{reset}
''' '''

View File

@@ -1,16 +1,37 @@
import os
import sys import sys
import platform
from datetime import datetime
# Colors will be unavailable on non-linux machines
colors = True colors = True
machine = sys.platform machine = sys.platform
# Colors will be unavailable on non-linux machines
if machine.lower().startswith(("os", "win", "darwin","ios")): if machine.lower().startswith(("os", "win", "darwin","ios")):
colors = False colors = False
if not colors: if not colors:
reset = red = white = green = "" reset = red = white = green = green_bg = white_bg = red_bg = ""
else: else:
white = "\033[97m" date_time = datetime.now()
red = "\033[91m" print(f"\n\t OCTOSUITE © 2022 Richard Mwewa\n\t{date_time.strftime('%A %d %B %Y, %H:%M:%S%p')}\n\n\nOS: {platform.system()}\nProcessor: {platform.processor()}\nNode: {platform.node()}\nRelease: {platform.release()}\nArchitecture: {platform.architecture()}\nVersion: {platform.version()}\n\n")
reset = "\033[0m" while True:
green = "\033[92m" try:
color_chooser = input(f"[ ? ] Welcome {os.getlogin()}, would you like to enable colors for this session? (y/n) ")
if color_chooser.lower() == "y":
white = "\033[97m"
white_bg = "\033[47;30m"
red = "\033[91m"
reset = "\033[0m"
green = "\033[92m"
green_bg = "\033[42;37m"
red_bg = "\033[41;37m"
break
elif color_chooser.lower() == "n":
red = white = green = green_bg = white_bg = red_bg = reset = ""
break
else:
print(f"\n[ ! ] Your response ({color_chooser}) is invalid (expected y or n)")
except KeyboardInterrupt:
exit(f"[ ! ] Process interrupted with Ctrl+C")

View File

@@ -2,19 +2,16 @@
import logging import logging
from src.main import * from src.main import *
from lib.colors import red,white,green,reset from lib.colors import red,red_bg,white,reset
if __name__ == '__main__': if __name__ == '__main__':
while True: try:
try: octosuite().on_start()
octosuite().on_start()
except KeyboardInterrupt:
except KeyboardInterrupt: logging.warning('Process interrupted with Ctrl+C')
logging.info('Process interrupted with Ctrl+C') exit(f'\n{white}[{red} x {white}] Process interrupted with {red_bg}Ctrl+C{reset}')
exit(f'\n{white}[{red}x{white}] Process interrupted with {red}Ctrl{white}+{red}C{reset}')
except Exception as e:
logging.error(f'Session terminated on error: {e}')
except Exception as e: exit(f'\n{white}[{red} ! {white}] Session {red_bg}terminated{reset}{white} on error: {red}{e}{reset}')
logging.error(f'An error occured: {e}')
print(f'{white}[{red}!{white}] An error occured: {red}{e}{reset}')
input(f'\n{white}^ Press any key to continue{reset} ')

View File

@@ -14,6 +14,7 @@
''' '''
import os import os
import sys
import logging import logging
import requests import requests
import platform import platform
@@ -22,10 +23,35 @@ from tqdm import tqdm
from pprint import pprint from pprint import pprint
from lib.banner import banner from lib.banner import banner
from datetime import datetime from datetime import datetime
from lib.colors import red, white, green, reset from lib.colors import red, white, green, green_bg, white_bg, red_bg, reset
class octosuite: class octosuite:
def __init__(self): def __init__(self):
# A list of tuples, mapping commands to their respective functionalities
self.commands_base = [('info:org', self.org_info),
('info:user', self.user_profile),
('info:repo', self.repo_info),
('path:contents', self.path_contents),
('repos:org', self.org_repos),
('repos:user', self.user_repos),
('user:gists', self.user_gists),
('user:followers', self.followers),
('user:following', self.following),
('search:users', self.user_search),
('search:repos', self.repo_search),
('search:topics', self.topic_search),
('search:issues', self.issue_search),
('search:commits', self.commits_search),
('logs:view',self.view_logs),
('logs:read',self.read_log),
('logs:delete',self.delete_log),
('update', self.update),
('changelog', self.changelog),
('info:dev', self.author),
('help', self.help),
('exit', self.exit_session)]
# Path attribute # Path attribute
self.path_attrs =['size','type','path','sha','html_url'] self.path_attrs =['size','type','path','sha','html_url']
# Path attribute dictionary # Path attribute dictionary
@@ -35,6 +61,7 @@ class octosuite:
'sha': 'SHA', 'sha': 'SHA',
'html_url': 'URL'} 'html_url': 'URL'}
# Organization attributes # Organization attributes
self.org_attrs = ['avatar_url','login','id','node_id','email','description','blog','location','followers','following','twitter_username','public_gists','public_repos','type','is_verified','has_organization_projects','has_repository_projects','created_at','updated_at'] self.org_attrs = ['avatar_url','login','id','node_id','email','description','blog','location','followers','following','twitter_username','public_gists','public_repos','type','is_verified','has_organization_projects','has_repository_projects','created_at','updated_at']
# Organization attribute dictionary # Organization attribute dictionary
@@ -57,6 +84,8 @@ class octosuite:
'has_repository_projects': 'Has repository projects?', 'has_repository_projects': 'Has repository projects?',
'created_at': 'Created at', 'created_at': 'Created at',
'updated_at': 'Updated at'} 'updated_at': 'Updated at'}
# Repository attributes # Repository attributes
self.repo_attrs = ['id','description','forks','allow_forking','fork','stargazers_count','watchers','license','default_branch','visibility','language','open_issues','topics','homepage','clone_url','ssh_url','private','archived','has_downloads','has_issues','has_pages','has_projects','has_wiki','pushed_at','created_at','updated_at'] self.repo_attrs = ['id','description','forks','allow_forking','fork','stargazers_count','watchers','license','default_branch','visibility','language','open_issues','topics','homepage','clone_url','ssh_url','private','archived','has_downloads','has_issues','has_pages','has_projects','has_wiki','pushed_at','created_at','updated_at']
# Repository attribute dictionary # Repository attribute dictionary
@@ -88,6 +117,7 @@ class octosuite:
'created_at': 'Created at', 'created_at': 'Created at',
'updated_at': 'Updated at'} 'updated_at': 'Updated at'}
# Profile attributes # Profile attributes
self.profile_attrs = ['avatar_url','login','id','node_id','bio','blog','location','followers','following','twitter_username','public_gists','public_repos','company','hireable','site_admin','created_at','updated_at'] self.profile_attrs = ['avatar_url','login','id','node_id','bio','blog','location','followers','following','twitter_username','public_gists','public_repos','company','hireable','site_admin','created_at','updated_at']
# Profile attribute dictionary # Profile attribute dictionary
@@ -109,6 +139,7 @@ class octosuite:
'created_at': 'Joined at', 'created_at': 'Joined at',
'updated_at': 'Updated at'} 'updated_at': 'Updated at'}
# User attributes # User attributes
self.user_attrs = ['avatar_url','id','node_id','gravatar_id','site_admin','type','html_url'] self.user_attrs = ['avatar_url','id','node_id','gravatar_id','site_admin','type','html_url']
# User attribute dictionary # User attribute dictionary
@@ -119,6 +150,7 @@ class octosuite:
'site_admin': 'Is site admin?', 'site_admin': 'Is site admin?',
'type': 'Account type', 'type': 'Account type',
'html_url': 'URL'} 'html_url': 'URL'}
# Topic atrributes # Topic atrributes
self.topic_attrs = ['score','curated','featured','display_name','created_by','created_at','updated_at'] self.topic_attrs = ['score','curated','featured','display_name','created_by','created_at','updated_at']
@@ -130,6 +162,7 @@ class octosuite:
'created_by': 'Created by', 'created_by': 'Created by',
'created_at': 'Created at', 'created_at': 'Created at',
'updated_at': 'Updated at'} 'updated_at': 'Updated at'}
# Gists attributes # Gists attributes
self.gists_attrs = ['node_id','description','comments','files','git_push_url','public','truncated','updated_at'] self.gists_attrs = ['node_id','description','comments','files','git_push_url','public','truncated','updated_at']
@@ -143,6 +176,7 @@ class octosuite:
'truncated': 'Is truncated?', 'truncated': 'Is truncated?',
'updated_at': 'Updated at'} 'updated_at': 'Updated at'}
# Issue attributes # Issue attributes
self.issue_attrs = ['id','node_id','score','state','number','comments','milestone','assignee','assignees','labels','locked','draft','closed_at','body'] self.issue_attrs = ['id','node_id','score','state','number','comments','milestone','assignee','assignees','labels','locked','draft','closed_at','body']
# Issue attribute dict # Issue attribute dict
@@ -162,75 +196,44 @@ class octosuite:
'created_at': 'Created at', 'created_at': 'Created at',
'body': 'Body'} 'body': 'Body'}
# Author dictionary # Author dictionary
self.author_dict = {'Alias': 'rly0nheart', self.author_dict = {'Alias': 'rly0nheart',
'Country': 'Zambia, Africa', 'Country': 'Zambia, Africa',
'About.me': 'https://about.me/rly0nheart'} 'About.me': 'https://about.me/rly0nheart'}
def on_start(self): def on_start(self):
logging.info(f'Started new session on {platform.node()}') # Start new session
logging.info(f'Started new session on {platform.node()}:{os.getlogin()}')
# Use 'cls' to clear screen on Windows based machines
# Otherwise, use 'clear'
while True: while True:
if platform.system() == 'Windows': if sys.platform.lower().startswith(('win','darwin')):
subprocess.run(['cls']) subprocess.run(['cls'])
else: else:
subprocess.run(['clear'],shell=False) subprocess.run(['clear'],shell=False)
print(banner) print(banner)
command = input(f'''{white}┌─({red}{os.getlogin()}{white}@{red}octosuite{white})-[{green}{os.getcwd()}{white}]\n╼[{green}:~{white}]{reset} ''') command_input = input(f'''{white}┌─({red}{os.getlogin()}{white}@{red}octosuite{white})-[{green}{os.getcwd()}{white}]\n└╼[{green}:~{white}]{reset} ''')
if command == 'orginfo': # Looping through the commands base to check if the user input command matches any command in the commands base, and return its functionality
self.org_info() # If no match is found, we ignore it
elif command == 'userinfo': for command, functionality in self.commands_base:
self.user_profile() if command == command_input:
elif command == 'repoinfo': functionality()
self.repo_info() else:
elif command == 'pathcontents': pass
self.path_contents()
elif command == 'orgrepos': input(f'\n{white}[{green} ? {white}] Press {white_bg}any key{reset}{white} to continue{reset} ')
self.org_repos()
elif command == 'userrepos':
self.user_repos()
elif command == 'usergists':
self.user_gists()
elif command == 'userfollowers':
self.followers()
elif command == 'userfollowing':
self.following()
elif command == 'usersearch':
self.user_search()
elif command == 'reposearch':
self.repo_search()
elif command == 'topicsearch':
self.topic_search()
elif command == 'issuesearch':
self.issue_search()
elif command == 'commitsearch':
self.commits_search()
elif command == 'update':
self.update()
elif command == 'changelog':
print(self.changelog())
elif command == 'author':
self.author()
elif command == 'ilinso':
self.easter_egg()
elif command == 'help':
print(self.help())
elif command == 'exit':
logging.info('Session terminated with \'exit\' command')
exit(f'\n{white}[{red}-{white}] Session terminated with \'exit\' command{reset}')
else:
print(f'\n{white}[{red}!{white}] Command not found: {command}{reset}')
logging.warning(f'command not found: {command}')
input(f'\n{white}[{green}?{white}] Press any key to continue{reset} ')
# Fetching organization info
def org_info(self): def org_info(self):
organization = input(f'{white}@{green}Organization {white}>>{reset} ') organization = input(f'\n{white}[{white_bg}@Organization{reset}{white}] (username){reset} ')
api = f'https://api.github.com/orgs/{organization}' api = f'https://api.github.com/orgs/{organization}'
response = requests.get(api) response = requests.get(api)
if response.status_code != 200: if response.status_code != 200:
print(f'\n{white}[{red}-{white}] Organization @{organization} {red}Not Found{reset}') print(f'\n{white}[{red}-{white}] Organization @{organization} {red_bg}Not Found{reset}')
else: else:
response = response.json() response = response.json()
print(f"\n{white}{response['name']}{reset}") print(f"\n{white}{response['name']}{reset}")
@@ -240,11 +243,11 @@ class octosuite:
# Fetching user information # Fetching user information
def user_profile(self): def user_profile(self):
username = input(f'{white}@{green}Username{white} >> {reset}') username = input(f'\n{white}[{white_bg}@Username{reset}{white}]{reset} ')
api = f'https://api.github.com/users/{username}' api = f'https://api.github.com/users/{username}'
response = requests.get(api) response = requests.get(api)
if response.status_code != 200: if response.status_code != 200:
print(f'\n{white}[{red}-{white}] User @{username} {red}Not Found{reset}') print(f'\n{white}[{red} - {white}] User @{username} {red_bg}Not Found{reset}')
else: else:
response = response.json() response = response.json()
print(f"\n{white}{response['name']}{reset}") print(f"\n{white}{response['name']}{reset}")
@@ -254,12 +257,12 @@ class octosuite:
# Fetching repository information # Fetching repository information
def repo_info(self): def repo_info(self):
username = input(f'{white}@{green}Owner-username{white} >> {reset}') repo_name = input(f'\n{white}[{white_bg}%reponame{reset}{white}]{reset} ')
repo_name = input(f'{white}%{green}reponame{white} >> {reset}') username = input(f'{white}[{white_bg}@Owner{reset}{white}] (username){reset} ')
api = f'https://api.github.com/repos/{username}/{repo_name}' api = f'https://api.github.com/repos/{username}/{repo_name}'
response = requests.get(api) response = requests.get(api)
if response.status_code != 200: if response.status_code != 200:
print(f'\n{white}[{red}-{white}] Repository %{repo_name} {red}Not Found{reset}') print(f'\n{white}[{red} - {white}] Repository %{repo_name} or user @{username} {red_bg}Not Found{reset}')
else: else:
response = response.json() response = response.json()
print(f"\n{white}{response['full_name']}{reset}") print(f"\n{white}{response['full_name']}{reset}")
@@ -269,13 +272,13 @@ class octosuite:
# Get path contents # Get path contents
def path_contents(self): def path_contents(self):
username = input(f'{white}@{green}Owner-username{white} >> {reset}') repo_name = input(f'\n{white}[{white_bg}%reponame{reset}{white}]{reset} ')
repo_name = input(f'{white}%{green}reponame{white} >> {reset}') username = input(f'{white}[{white_bg}@Owner{reset}{white}] (username){reset} ')
path_name = input(f'{white}/path/name >>{reset} ') path_name = input(f'{white}[{white_bg}/path/name{reset}{white}]{reset} ')
api = f'https://api.github.com/repos/{username}/{repo_name}/contents/{path_name}' api = f'https://api.github.com/repos/{username}/{repo_name}/contents/{path_name}'
response = requests.get(api) response = requests.get(api)
if response.status_code != 200: if response.status_code != 200:
print(f'\n{white}[{red}-{white}] Information {red}Not Found{reset}') print(f'\n{white}[{red} - {white}] Information {red_bg}Not Found{reset}')
else: else:
response = response.json() response = response.json()
for item in response: for item in response:
@@ -284,13 +287,13 @@ class octosuite:
print(f'{white}├─ {self.path_attr_dict[attr]}: {green}{item[attr]}{reset}') print(f'{white}├─ {self.path_attr_dict[attr]}: {green}{item[attr]}{reset}')
# Fetching organozation repositories # Fetching organization repositories
def org_repos(self): def org_repos(self):
organization = input(f'{white}@{green}Organization{white} >> {reset}') organization = input(f'\n{white}[{white_bg}@Organization{reset}{white}] (username){reset} ')
api = f'https://api.github.com/orgs/{organization}/repos?per_page=100' api = f'https://api.github.com/orgs/{organization}/repos?per_page=100'
response = requests.get(api) response = requests.get(api)
if response.status_code != 200: if response.status_code != 200:
print(f'\n{white}[{red}-{white}] Organization @{organization} {red}Not Found{reset}') print(f'\n{white}[{red} - {white}] Organization @{organization} {red_bg}Not Found{reset}')
else: else:
response = response.json() response = response.json()
for repo in response: for repo in response:
@@ -302,11 +305,11 @@ class octosuite:
# Fetching user repositories # Fetching user repositories
def user_repos(self): def user_repos(self):
username = input(f'{white}@{green}Username{white} >> {reset}') username = input(f'\n{white}[{white_bg}@Username{reset}{white}]{reset} ')
api = f'https://api.github.com/users/{username}/repos?per_page=100' api = f'https://api.github.com/users/{username}/repos?per_page=100'
response = requests.get(api) response = requests.get(api)
if response.status_code != 200: if response.status_code != 200:
print(f'\n{white}[{red}-{white}] User @{username} {red}Not Found{reset}') print(f'\n{white}[{red} - {white}] User @{username} {red_bg}Not Found{reset}')
else: else:
response = response.json() response = response.json()
for repo in response: for repo in response:
@@ -318,11 +321,13 @@ class octosuite:
# Fetching user's gists # Fetching user's gists
def user_gists(self): def user_gists(self):
username = input(f'{white}@{green}Username{white} >> {reset}') username = input(f'\n{white}[{white_bg}@Username{reset}{white}]{reset} ')
api = f'https://api.github.com/users/{username}/gists' api = f'https://api.github.com/users/{username}/gists'
response = requests.get(api).json() response = requests.get(api).json()
if response == []: if response == []:
print(f'{white}[{red}-{white}]User @{username} does not have any active gists.{reset}') print(f'\n{white}[{red} - {white}] User @{username} {red_bg}does not{reset}{white} have any active gists.{reset}')
elif "Not Found" in response['message']:
print(f'\n{white}[{red} - {white}] User @{username} {red_bg}Not Found{reset}')
else: else:
for item in response: for item in response:
print(f"\n{white}{item['id']}{reset}") print(f"\n{white}{item['id']}{reset}")
@@ -333,11 +338,13 @@ class octosuite:
# Fetching user's followera' # Fetching user's followera'
def followers(self): def followers(self):
username = input(f'{white}@{green}Username{white} >> {reset}') username = input(f'\n{white}[{white_bg}@Username{reset}{white}]{reset} ')
api = f'https://api.github.com/users/{username}/followers?per_page=100' api = f'https://api.github.com/users/{username}/followers?per_page=100'
response = requests.get(api).json() response = requests.get(api).json()
if response == []: if response == []:
print(f'\n{white}[{red}-{white}]User @{username} does not have followers.{reset}') print(f'\n{white}[{red} - {white}]User @{username} {red_bg}does not{reset}{white} have followers.{reset}')
elif "Not Found" in response['message']:
print(f'\n{white}[{red} - {white}] User @{username} {red_bg}Not Found{reset}')
else: else:
for item in response: for item in response:
print(f"\n{white}@{item['login']}{reset}") print(f"\n{white}@{item['login']}{reset}")
@@ -348,19 +355,19 @@ class octosuite:
# Checking whether or not user[A] follows user[B] # Checking whether or not user[A] follows user[B]
def following(self): def following(self):
user_a = input(f'{white}@{green}User[A]{white} >> {reset}') user_a = input(f'\n{white}[{white_bg}@User A{reset}{white}] (username){reset} ')
user_b = input(f'{white}@{green}User[B]{white} >> {reset}') user_b = input(f'{white}[{white_bg}@User B{reset}{white}] (username){reset} ')
api = f'https://api.github.com/users/{user_a}/following/{user_b}' api = f'https://api.github.com/users/{user_a}/following/{user_b}'
response = requests.get(api) response = requests.get(api)
if response.status_code == 204: if response.status_code == 204:
print(f'{white}[{green}+{white}] @{user_a} follows @{user_b}.{reset}') print(f'\n{white}[{green} + {white}] @{user_a} {green_bg}follows{reset}{white} @{user_b}.{reset}')
else: else:
print(f'{white}[{red}-{white}] @{user_a} does not follow @{user_b}.{reset}') print(f'\n{white}[{red} - {white}] @{user_a} {red_bg}does not{reset}{white} follow @{user_b}.{reset}')
# User search # User search
def user_search(self): def user_search(self):
query = input(f'{white}#{green}Query{white} >> {reset}') query = input(f'\n{white}[{white_bg}#@Query{reset}{white}]{reset} ')
api = f'https://api.github.com/search/users?q={query}&per_page=100' api = f'https://api.github.com/search/users?q={query}&per_page=100'
response = requests.get(api).json() response = requests.get(api).json()
for item in response['items']: for item in response['items']:
@@ -372,7 +379,7 @@ class octosuite:
# Repository search # Repository search
def repo_search(self): def repo_search(self):
query = input(f'{white}#{green}Query{white} >> {reset}') query = input(f'\n{white}[{white_bg}#%Query{reset}{white}]{reset} ')
api = f'https://api.github.com/search/repositories?q={query}&per_page=100' api = f'https://api.github.com/search/repositories?q={query}&per_page=100'
response = requests.get(api).json() response = requests.get(api).json()
for item in response['items']: for item in response['items']:
@@ -384,7 +391,7 @@ class octosuite:
# Topics search # Topics search
def topic_search(self): def topic_search(self):
query = input(f'{white}#{green}Query{white} >> {reset}') query = input(f'\n{white}[{white_bg}##Query{reset}{white}]{reset} ')
api = f'https://api.github.com/search/topics?q={query}&per_page=100' api = f'https://api.github.com/search/topics?q={query}&per_page=100'
response = requests.get(api).json() response = requests.get(api).json()
for item in response['items']: for item in response['items']:
@@ -396,7 +403,7 @@ class octosuite:
# Issue search # Issue search
def issue_search(self): def issue_search(self):
query = input(f'{white}#{green}Query{white} >> {reset}') query = input(f'\n{white}[{white_bg}#!Query{reset}{white}]{reset} ')
api = f'https://api.github.com/search/issues?q={query}&per_page=100' api = f'https://api.github.com/search/issues?q={query}&per_page=100'
response = requests.get(api).json() response = requests.get(api).json()
for item in response['items']: for item in response['items']:
@@ -408,53 +415,73 @@ class octosuite:
# Commits search # Commits search
def commits_search(self): def commits_search(self):
query = input(f'{white}#{green}Query{white} >> {reset}') query = input(f'\n{white}[{white_bg}#:Query{reset}{white}]{reset} ')
api = f'https://api.github.com/search/commits?q={query}&per_page=100' api = f'https://api.github.com/search/commits?q={query}&per_page=100'
response = requests.get(api).json() response = requests.get(api).json()
n=0 number=0
for item in response['items']: for item in response['items']:
n+=1 number+=1
print(f'{white}{n}.{reset}') print(f'{white}{number}.{reset}')
pprint(item['commit']) pprint(item['commit'])
print('\n') print('\n')
# View octosuite log files
def view_logs(self):
logs = os.listdir('.logs')
print(f"\n {red_bg}[LOG] [SIZE] {reset}")
for log in logs:
print(f" {log}\t ",os.path.getsize(".logs/"+log),"bytes")
print(f" {red_bg} {reset}")
# Delete a specified log file
def delete_log(self):
log_file = input(f"\n{white}[{white_bg}logfile{reset}{white}]{reset} ")
if sys.platform.lower().startswith(('win','darwin')):
subprocess.run(['del',f'{os.getcwd()}/.logs/{log_file}'])
else:
subprocess.run(['sudo','rm',f'.logs/{log_file}'],shell=False)
logging.info(f'Deleted log file: {log_file}')
print(f"{white}[{green} + {white}] Deleted log file: {green}{log_file}{reset}")
# Read a specified log file
def read_log(self):
log_file = input(f"\n{white}[{white_bg}logfile{reset}{white}]{reset} ")
with open(f'.logs/{log_file}', 'r') as log:
logging.info(f'Reading log file: {log_file}')
print("\n"+log.read())
# Update program # Update program
def update(self): def update(self):
logging.info('Fetching updates...') logging.info('Updating...')
files_to_update = ['src/main.py','lib/banner.py','lib/colors.py','octosuite','.github/dependabot.yml','LICENSE','README.md','requirements.txt'] files_to_update = ['src/main.py','lib/banner.py','lib/colors.py','octosuite','.github/dependabot.yml','.github/ISSUE_TEMPLATE/bug_report.md','.github/ISSUE_TEMPLATE/feature_request.md','.github/ISSUE_TEMPLATE/config.yml','LICENSE','README.md','requirements.txt']
for file in tqdm(files_to_update,desc=f'{white}[{green}*{white}] Updating{reset}'): for file in tqdm(files_to_update,desc=f'{white}[{green} * {white}] Updating{reset}'):
data = requests.get(f'https://raw.githubusercontent.com/rly0nheart/octosuite/master/{file}') data = requests.get(f'https://raw.githubusercontent.com/rly0nheart/octosuite/master/{file}')
with open(file, 'wb') as code: with open(file, 'wb') as code:
code.write(data.content) code.write(data.content)
code.close() code.close()
logging.info('Update complete.') logging.info('Update complete.')
exit(f'{white}[{green}+{white}] Updated successfully. Re-run octosuite.{reset}') exit(f'{white}[{green} + {white}] {green_bg}Updated{reset}{white} successfully. Re-run octosuite.{reset}')
def easter_egg(self):
print(f'\n{white}[{green}*{white}] Downloading. Please wait...{reset}')
file = requests.get('https://drive.google.com/uc?export=download&id=1IRu4kWSuNpYWH8hZkqQ8mLnv4sSDu-GN')
with open('EasterEgg.zip','wb') as f:
f.write(file.content)
exit(f'{white}[{green}+{white}] Downloaded (EasterEgg.zip).\n{white}[{green}!{white}] The password is: {green}horus{white}\n[{green}!{white}] Happy hunting! :).{reset}')
# Show changelog # Show changelog
def changelog(self): def changelog(self):
# lol yes the changelog is hard coded # lol yes the changelog is hard coded
changelog_text = ''' changelog_text = f'''
v1.5.1-beta CHANGELOG:
{red_bg}v1.7.0-dev [CHANGELOG] {reset}
• First pypi package release • Changed (y/n) behavior in color chooser (where any input apart from 'y' was considered as 'n')
• Termux users will now have to manually create the .logs folder • Added 'logs:view' command for viewing octosuite logs
• Changed logs date/time format • Added 'logs:read' command for reading a specified log file
• Removed 1 internal dependency • Added 'logs:delete' command for deleting a specified log file
• There's an easter egg somewhere in here ;) (use the command 'ilinso') • Minor improvements
''' {red_bg} {reset}'''
return changelog_text print(changelog_text)
# Author info # Author info
@@ -463,47 +490,56 @@ class octosuite:
for key,value in self.author_dict.items(): for key,value in self.author_dict.items():
print(f'{white}├─ {key}: {green}{value}{reset}') print(f'{white}├─ {key}: {green}{value}{reset}')
# Close session
def exit_session(self):
logging.info('Session closed with \'exit\' command.')
exit(f'\n{white}[{green} ! {white}] Session closed with {white_bg}exit{reset}{white} command.{reset}')
# Help/usage
def help(self): def help(self):
help = f''' help = f'''
help:
{white}Command Descritption {red_bg}[COMMAND] [DESCRIPTION] {reset}
------------ --------------------------------------------------------- info:org Get target organization info
{green}orginfo{white} --> Get target organization info{reset} info:user Get target user profile info
{green}userinfo{white} --> Get target user profile info{reset} info:repo Get target repository info
{green}repoinfo{white} --> Get target repository info{reset} info:dev Show developer's info
{green}pathcontents{white} --> Get contents of a specified path from a target repository{reset} path:contents Get contents of a specified path from a target repository
{green}orgrepos{white} --> Get a list of repositories owned by a target organization{reset} repos:org Get a list of repositories owned by a target organization
{green}userrepos{white} --> Get a list of repositories owned by a target user{reset} repos:user Get a list of repositories owned by a target user
{green}usergists{white} --> Get a list of gists owned by a target user{reset} user:gists Get a list of gists owned by a target user
{green}userfollowers{white} --> Get a list of the target's followers{reset} user:followers Get a list of the target's followers
{green}userfollowing{white} --> Check whether or not User[A] follows User[B]{reset} user:following Check whether or not User[A] follows User[B]
{green}usersearch{white} --> Search user(s){reset} search:users Search user(s)
{green}reposearch{white} --> Search repositor[y][ies]{reset} search:repos Search repositor[y][ies]
{green}topicsearch{white} --> Search topic(s){reset} search:topics Search topic(s)
{green}issuesearch{white} --> Search issue(s){reset} search:issues Search issue(s)
{green}commitsearch{white} --> Search commit(s){reset} search:commits Search commit(s)
{green}update{white} --> Update octosuite{reset} logs:view View log files
{green}changelog{white} --> Show changelog{reset} logs:read Read a specified log file
{green}author{white} --> Show author info{reset} logs:delete Delete a specified log file
{green}help{white} --> Show usage/help{reset} update Update octosuite
{green}exit{white} --> Exit session{reset} changelog Show changelog
{white}------------ ---------------------------------------------------------{reset} help Show usage/help
''' exit Exit session
return help {red_bg} {reset}'''
print(help)
# If .logs folder exists, pass
if os.path.exists('.logs'): if os.path.exists('.logs'):
pass pass
else: else:
# Creating the .logs directory # Creating the .logs directory
if platform.system() == "Windows": # If the current system is Windows based, we run mkdir command without sudo
# Else we run the mkdir command with sudo
if sys.platform.lower().startswith(('win','darwin')):
subprocess.run(['mkdir','.logs']) subprocess.run(['mkdir','.logs'])
else: else:
subprocess.run(['sudo','mkdir','.logs'],shell=False) subprocess.run(['sudo','mkdir','.logs'],shell=False)
# Set to automatically monitor and log network and user activity into the .logs folder # Set to automatically monitor and log network and user activity into the .logs folder
logging.basicConfig(filename=f'.logs/{datetime.now()}.log',format='%(asctime)s %(message)s',datefmt='%Y-%m-%d %H:%M:%S',level=logging.DEBUG) logging.basicConfig(filename=f'.logs/{datetime.now()}.log',format='[%(asctime)s] [%(levelname)s] %(message)s',datefmt='%Y-%m-%d %H:%M:%S%p',level=logging.DEBUG)