Compare commits

..

45 Commits
1.5.0 ... 1.9.0

Author SHA1 Message Date
Richard Mwewa
77ddfa4b02 Update README.md 2022-04-30 10:32:31 +02:00
Richard Mwewa
66192c2a63 Create .log 2022-04-30 10:30:49 +02:00
Richard Mwewa
f591764343 Update banner.py 2022-04-30 10:28:50 +02:00
Richard Mwewa
f6dbd8ec49 Update main.py 2022-04-30 10:27:11 +02:00
Richard Mwewa
99deaf04f3 Update main.py 2022-04-29 23:53:10 +02:00
Richard Mwewa
56eead2f26 Update README.md 2022-04-29 23:46:12 +02:00
Richard Mwewa
73e7c339e6 Update README.md 2022-04-29 23:26:32 +02:00
Richard Mwewa
3cd6442d91 Update README.md 2022-04-28 01:33:21 +02:00
Richard Mwewa
7ebb90790a Update banner.py 2022-04-28 01:10:39 +02:00
Richard Mwewa
ca0d2dc268 Update main.py 2022-04-28 01:08:26 +02:00
Richard Mwewa
51babb3c45 Update README.md 2022-04-27 17:09:33 +02:00
Richard Mwewa
12e9dbcae9 Update main.py 2022-04-27 15:31:31 +02:00
Richard Mwewa
be4e88d99b Update banner.py 2022-04-27 15:29:53 +02:00
Richard Mwewa
f7ac0fb8d5 Update colors.py 2022-04-27 15:28:07 +02:00
Richard Mwewa
fc7a65c593 Update octosuite 2022-04-27 15:25:15 +02:00
Richard Mwewa
51f2a46c65 Delete tmp 2022-04-23 14:10:18 +02:00
Richard Mwewa
4afbc5adaa Create tmp 2022-04-23 14:09:35 +02:00
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
Richard Mwewa
6d1e163d9a Update LICENSE 2022-04-11 13:03:07 +02:00
Richard Mwewa
a8730864e9 Update README.md 2022-04-11 13:01:03 +02:00
Richard Mwewa
315cb7ec6f Update colors.py 2022-04-11 12:59:10 +02:00
Richard Mwewa
2afac6c0d4 Update banner.py 2022-04-11 12:58:23 +02:00
Richard Mwewa
b226f1b53b Update main.py 2022-04-11 12:56:19 +02:00
Richard Mwewa
bb38d95e57 Update README.md 2022-04-09 21:18:56 +02:00
Richard Mwewa
eae41866ec Create config.yml 2022-04-09 20:57:07 +02:00
Richard Mwewa
1e71c2d3bd Create feature_request.md 2022-04-09 20:42:46 +02:00
Richard Mwewa
d91f88d31b Create bug_report.md 2022-04-09 20:40:44 +02:00
10 changed files with 394 additions and 224 deletions

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Richard Mwewa (Telegram)
url: https://t.me/rly0nheart/
about: Please ask and answer questions here.
- name: Richard Mwewa (Twitter)
url: https://m.twitter.com/rly0nheart/
about: Please report security vulnerabilities or bugs here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1,3 +1,4 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
@@ -631,8 +632,8 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
octosuite Advanced Github OSINT Framework
Copyright (C) 2022 Richard Mwewa
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

110
README.md
View File

@@ -1,15 +1,22 @@
![Screenshot_2022-03-17_10-12-53](https://user-images.githubusercontent.com/74001397/158868105-b5aba7e8-7342-4268-bd7a-6d6ae0bdae5a.png)
![octosuite](https://user-images.githubusercontent.com/74001397/165550323-d880e320-a4c0-4f4e-87dd-d2e8319554ec.png)
![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/rly0nheart/octosuite?style=for-the-badge&logo=github)
![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-Mac-blue?style=for-the-badge&logo=apple)
![OS](https://img.shields.io/badge/OS-Mac-white?style=for-the-badge&logo=apple)
![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.9.0?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)
> *Simply gather OSINT on Github users and organizations like a god🔥*
> *Simply gather OSINT on Github users & organizations like a God🔥*
# INSTALLATION
Installation instructions are on the wiki, in addition to all other documentation.
[Refer to the Wiki](https://github.com/rly0nheart/octosuite/wiki)
***
# FEATURES
- [x] Fetches organization info
- [x] Fetches user info
@@ -27,72 +34,57 @@
- [x] Searches commits
- [x] Easily updates with the 'update' command
- [x] Automatically logs network activity (.logs folder)
- [x] User can view, read and delete log files
# INSTALLATION
**clone project**:
```
git clone https://github.com/rly0nheart/octosuite.git
```
```
cd octosuite
```
```
pip install -r requirements.txt
```
# USAGE
**Linux**:
```
sudo chmod +x octosuite
```
```
sudo ./octosuite
```
**Windows**:
```
python3 octosuite
```
**Mac**:
```
python3 octosuite
```
***
# AVAILABLE COMMANDS
| Command | Usage|
| COMMAND | DESCRIPTION|
| ------------- |:---------:|
| ``orginfo`` | *get organization info* |
| ``userinfo`` | *get user profile info* |
| ``repoinfo`` | *get repository info* |
| ``pathcontents`` | *get contents of a path from a specified repository* |
| ``orgrepos`` | *get a list of repositories owned by a specified organization* |
| ``userrepos`` | *get a list of repositories owned by a specified user* |
| ``usergists`` | *get a list of gists owned by a specified user* |
| ``userfollowers`` | *get a list of a user's followers* |
| ``userfollowing`` | *check whether user A follows user B* |
| ``usersearch`` | *search user(s)* |
| ``reposearch`` | *search repositor(y)(ies)* |
| ``topicsearch`` | *search topics(s)* |
| ``issuesearch`` | *search issue(s)* |
| ``commitsearch`` | *search commit(s)* |
| ``info:org`` | *get organization info* |
| ``info:user`` | *get user profile info* |
| ``info:repo`` | *get repository info* |
| ``info:dev`` | *show developer's info* |
| ``path:contents`` | *get contents of a path from a specified repository* |
| ``repos:org`` | *get a list of repositories owned by a specified organization* |
| ``repos:user`` | *get a list of repositories owned by a specified user* |
| ``user:gists`` | *get a list of gists owned by a specified user* |
| ``user:followers`` | *get a list of a user's followers* |
| ``user:following`` | *check whether user A follows user B* |
| ``search:users`` | *search user(s)* |
| ``search:repos`` | *search repositor(y)(ies)* |
| ``search:topics`` | *search topics(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* |
| ``changelog`` | *show changelog* |
| ``author`` | *show author info* |
| ``help`` | *show usage/help* |
| ``exit`` | *exit session* |
# NOTE
***
# NOTES
* *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***
* *If you believe octosuite can be better, feel free to open a pull request with your improvements* ✌🏾🙂
***
# PYPI
[PyPI Package](https://pypi.org/project/octosuite)
![PyPI Downloads](https://pepy.tech/badge/octosuite)
***
# LICENSE
![license](https://user-images.githubusercontent.com/74001397/137917929-2f2cdb0c-4d1d-4e4b-9f0d-e01589e027b5.png)
# ABOUT AUTHOR
***
# ABOUT DEVELOPER
[About.me](https://about.me/rly0nheart)
***
# DONATIONS
Love octosuite? Please consider buying me a coffee, I will appreciate really it. ☕👌🏾😊
<a href="https://www.buymeacoffee.com/189381184" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a>

View File

@@ -1,19 +1,25 @@
from lib.colors import red,white,green,reset
import os
from lib.colors import red, white, green, red_bg,reset
version = 'v1.9.0'
banner = f'''{red}
▒█████ ▄████▄ ▄▄▄█████▓ ▒█████ ██████ █ ██ ██▓▄▄▄█████▓▓█████
▒██▒ ██▒▒██▀ ▀█ ▓ ██▒ ▓▒▒██▒ ██▒▒██ ▒ ██ ▓██▒▓██▒▓ ██▒ ▓▒▓█ ▀
▒██░ ██▒▒▓█ ▄ ▒ ▓██░ ▒░▒██░ ██▒░ ▓██▄ ▓██ ▒██░▒██▒▒ ▓██░ ▒░▒███
▒██ ██░▒▓▓▄ ▄██▒░ ▓██▓ ░ ▒██ ██░ ▒ ██▒▓▓█ ░██░░██░░ ▓██▓ ░ ▒▓█ ▄
░ ████▓▒░▒ ▓███▀ ░ ▒██▒ ░ ░ ████▓▒░▒██████▒▒▒█████▓ ░██░ ▒██▒ ░ ░▒████▒
░ ▒░▒░▒░ ░ ░▒ ▒ ░ ▒ ░░ ░ ▒░▒░▒░ ▒ ▒▓▒ ▒ ░░▒▓▒ ▒ ▒ ░▓ ▒ ░░ ░░ ▒░ ░
░ ▒ ▒░ ░ ▒ ░ ░ ▒ ▒░ ░ ░▒ ░ ░░░▒░ ░ ░ ▒ ░ ░ ░ ░ ░
░ ░ ░ ▒ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░░░ ░ ░ ▒ v1.5.0
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
{white}— Advanced Github {red}OSINT{white} Framework{reset}
▒█████ ▄████▄ ▄▄▄█████▓ ▒█████ ██████ █ ██ ██▓▄▄▄█████▓▓█████
▒██▒ ██▒▒██▀ ▀█ ▓ ██▒ ▓▒▒██▒ ██▒▒██ ▒ ██ ▓██▒▓██▒▓ ██▒ ▓▒▓█ ▀
▒██░ ██▒▒▓█ ▄ ▒ ▓██░ ▒░▒██░ ██▒░ ▓██▄ ▓██ ▒██░▒██▒▒ ▓██░ ▒░▒███
▒██ ██░▒▓▓▄ ▄██▒░ ▓██▓ ░ ▒██ ██░ ▒ ██▒▓▓█ ░██░░██░░ ▓██▓ ░ ▒▓█ ▄
░ ████▓▒░▒ ▓███▀ ░ ▒██▒ ░ ░ ████▓▒░▒██████▒▒▒█████▓ ░██░ ▒██▒ ░ ░▒████▒
░ ▒░▒░▒░ ░ ░▒ ▒ ░ ▒ ░░ ░ ▒░▒░▒░ ▒ ▒▓▒ ▒ ░░▒▓▒ ▒ ▒ ░▓ ▒ ░░ ░░ ▒░ ░
░ ▒ ▒░ ░ ▒ ░ ░ ▒ ▒░ ░ ░▒ ░ ░░░▒░ ░ ░ ▒ ░ ░ ░ ░ ░
░ ░ ░ ▒ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░░░ ░ ░ ▒ {red_bg} {version} {reset}{red}
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
{white}— Advanced Github {red}OSINT{white} Framework{reset}
> {white}Current user: {green}{os.getlogin()}{reset}
> {white}Use {green}help{reset}{white} command for usage{reset}
> {white}Commands are case sensitive{reset}
{'-'*27}
> {white}use '{green}help{white}' command for usage{reset}
> {white}commands are case sensitive
{'-'*30}
{reset}
'''

View File

@@ -1,16 +1,51 @@
import os
import sys
import platform
from datetime import datetime
# Colors will be unavailable on non-linux machines
colors = True
machine = sys.platform
if machine.lower().startswith(("os", "win", "darwin")):
machine = sys.platform
# Colors will be unavailable on non-linux machines
if machine.lower().startswith(("os", "win", "darwin","ios")):
colors = False
if not colors:
reset = red = white = green = ""
reset = red = white = green = red_bg = ""
else:
white = "\033[97m"
red = "\033[91m"
reset = "\033[0m"
green = "\033[92m"
else:
date_time = datetime.now()
sys_info = [("Processor",platform.processor),
("Node", platform.node),
("Release", platform.release),
("Architecture", platform.architecture),
("Version", platform.version)]
banner = f"""
OCTOSUITE © 2022 Richard Mwewa
{date_time.strftime('%A %d %B %Y, %H:%M:%S%p')}
{platform.system()}"""
print(banner)
for key, value in sys_info:
print(f"\t├─ {key}: {value()}")
print("\n")
while True:
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"
red = "\033[91m"
reset = "\033[0m"
green = "\033[92m"
red_bg = "\033[41;37m"
break
elif color_chooser.lower() == "n":
red = white = green = 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
from src.main import *
from lib.colors import red,white,green,reset
from lib.colors import red,white,reset
if __name__ == '__main__':
while True:
try:
octosuite().on_start()
except KeyboardInterrupt:
logging.info('Process interrupted with Ctrl+C')
exit(f'\n{white}[{red}x{white}] Process interrupted with {red}Ctrl{white}+{red}C{reset}')
except Exception as e:
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} ')
try:
octosuite().on_start()
except KeyboardInterrupt:
logging.warning('Session terminated with (Ctrl+C)')
exit(f'\n{white}[{red} x {white}] Session terminated with ({red}Ctrl{white}+{red}C{reset}{white}).{reset}')
except Exception as e:
logging.error(f'Session terminated on error: {e}')
exit(f'\n{white}[{red} ! {white}] Session terminated on error: {red}{e}{reset}')

View File

@@ -1,17 +1,57 @@
'''
octosuite Advanced Github OSINT Framework
Copyright (C) 2022 Richard Mwewa
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
'''
import os
import sys
import logging
import requests
import platform
import subprocess
import urllib.request
from tqdm import tqdm
from pprint import pprint
from lib.banner import banner
from datetime import datetime
from lib.colors import red, white, green, reset
from lib.banner import banner, version
from lib.colors import red, white, green, red_bg, reset
class octosuite:
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
self.path_attrs =['size','type','path','sha','html_url']
# Path attribute dictionary
@@ -21,6 +61,7 @@ class octosuite:
'sha': 'SHA',
'html_url': 'URL'}
# 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']
# Organization attribute dictionary
@@ -43,6 +84,8 @@ class octosuite:
'has_repository_projects': 'Has repository projects?',
'created_at': 'Created at',
'updated_at': 'Updated at'}
# 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']
# Repository attribute dictionary
@@ -74,6 +117,7 @@ class octosuite:
'created_at': 'Created at',
'updated_at': 'Updated at'}
# 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']
# Profile attribute dictionary
@@ -95,6 +139,7 @@ class octosuite:
'created_at': 'Joined at',
'updated_at': 'Updated at'}
# User attributes
self.user_attrs = ['avatar_url','id','node_id','gravatar_id','site_admin','type','html_url']
# User attribute dictionary
@@ -105,6 +150,7 @@ class octosuite:
'site_admin': 'Is site admin?',
'type': 'Account type',
'html_url': 'URL'}
# Topic atrributes
self.topic_attrs = ['score','curated','featured','display_name','created_by','created_at','updated_at']
@@ -116,6 +162,7 @@ class octosuite:
'created_by': 'Created by',
'created_at': 'Created at',
'updated_at': 'Updated at'}
# Gists attributes
self.gists_attrs = ['node_id','description','comments','files','git_push_url','public','truncated','updated_at']
@@ -129,6 +176,7 @@ class octosuite:
'truncated': 'Is truncated?',
'updated_at': 'Updated at'}
# Issue attributes
self.issue_attrs = ['id','node_id','score','state','number','comments','milestone','assignee','assignees','labels','locked','draft','closed_at','body']
# Issue attribute dict
@@ -148,73 +196,45 @@ class octosuite:
'created_at': 'Created at',
'body': 'Body'}
# Author dictionary
self.author_dict = {'Alias': 'rly0nheart',
'Country': 'Zambia, Africa',
'About.me': 'https://about.me/rly0nheart'}
'About.me': 'https://about.me/rly0nheart',
'BuyMeACoffee': 'https://buymeacoffee.com/189381184'}
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:
if platform.system() == 'Windows':
subprocess.run(['cls'])
if sys.platform.lower().startswith(('win','darwin')):
subprocess.run(['cls'])
else:
subprocess.run(['clear'],shell=False)
print(banner)
command = input(f'''{white}┌─({red}{platform.node()}{white}@{red}octosuite{white})-[{green}{os.getcwd()}{white}]\n╼[{green}:~{white}]{reset} ''')
if command == 'orginfo':
self.org_info()
elif command == 'userinfo':
self.user_profile()
elif command == 'repoinfo':
self.repo_info()
elif command == 'pathcontents':
self.path_contents()
elif command == 'orgrepos':
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 == 'help':
print(self.help())
elif command == 'exit':
logging.info('Session terminated.')
exit(f'\n{white}[{red}-{white}] Session terminated.{reset}')
else:
print(f'\n{white}[{red}!{white}] Unknown command: {command}{reset}')
logging.warning(f'Unknown command: {command}')
input(f'\n{white}^ Press any key to continue{reset} ')
command_input = input(f'''{white}┌─({red}{os.getlogin()}{white}@{red}octosuite{white})-[{green}{os.getcwd()}{white}]\n└╼[{green}:~{white}]{reset} ''')
# Looping through the commands base to check if the user input command matches any command in the commands base, and return its functionality
# If no match is found, we ignore it
for command, functionality in self.commands_base:
if command == command_input:
functionality()
else:
pass
input(f'\n{white}[{green} ? {white}] Press any key to continue{reset} ')
# Fetching organization info
def org_info(self):
organization = input(f'{white}@{green}Organization{white} >> {reset}')
organization = input(f'\n{white}--> @{green}organization{white} (username){reset} ')
api = f'https://api.github.com/orgs/{organization}'
response = requests.get(api)
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}) not found.{reset}')
else:
response = response.json()
print(f"\n{white}{response['name']}{reset}")
@@ -224,11 +244,11 @@ class octosuite:
# Fetching user information
def user_profile(self):
username = input(f'{white}@{green}Username{white} >> {reset}')
username = input(f'\n{white}--> @{green}username{reset} ')
api = f'https://api.github.com/users/{username}'
response = requests.get(api)
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}) not found.{reset}')
else:
response = response.json()
print(f"\n{white}{response['name']}{reset}")
@@ -238,12 +258,12 @@ class octosuite:
# Fetching repository information
def repo_info(self):
username = input(f'{white}@{green}Owner-username{white} >> {reset}')
repo_name = input(f'{white}%{green}reponame{white} >> {reset}')
repo_name = input(f'\n{white}--> %{green}reponame{reset} ')
username = input(f'{white}--> @{green}owner{white} (username){reset} ')
api = f'https://api.github.com/repos/{username}/{repo_name}'
response = requests.get(api)
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}) not found.{reset}')
else:
response = response.json()
print(f"\n{white}{response['full_name']}{reset}")
@@ -253,13 +273,13 @@ class octosuite:
# Get path contents
def path_contents(self):
username = input(f'{white}@{green}Owner-username{white} >> {reset}')
repo_name = input(f'{white}%{green}reponame{white} >> {reset}')
path_name = input(f'{white}/path/name >>{reset} ')
repo_name = input(f'\n{white}--> %{green}reponame{reset} ')
username = input(f'{white}--> @{green}owner{white} (username){reset} ')
path_name = input(f'{white}--> ~{green}/path/name{reset} ')
api = f'https://api.github.com/repos/{username}/{repo_name}/contents/{path_name}'
response = requests.get(api)
if response.status_code != 200:
print(f'\n{white}[{red}-{white}] Information {red}Not Found{reset}')
print(f'\n{white}[{red} - {white}] Information not found.{reset}')
else:
response = response.json()
for item in response:
@@ -268,13 +288,13 @@ class octosuite:
print(f'{white}├─ {self.path_attr_dict[attr]}: {green}{item[attr]}{reset}')
# Fetching organozation repositories
# Fetching organization repositories
def org_repos(self):
organization = input(f'{white}@{green}Organization{white} >> {reset}')
organization = input(f'\n{white}--> @{green}organization{white} (username){reset} ')
api = f'https://api.github.com/orgs/{organization}/repos?per_page=100'
response = requests.get(api)
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}) not found.{reset}')
else:
response = response.json()
for repo in response:
@@ -286,11 +306,11 @@ class octosuite:
# Fetching user repositories
def user_repos(self):
username = input(f'{white}@{green}Username{white} >> {reset}')
username = input(f'\n{white}--> @{green}username{reset} ')
api = f'https://api.github.com/users/{username}/repos?per_page=100'
response = requests.get(api)
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}) not found.{reset}')
else:
response = response.json()
for repo in response:
@@ -302,11 +322,13 @@ class octosuite:
# Fetching user's gists
def user_gists(self):
username = input(f'{white}@{green}Username{white} >> {reset}')
username = input(f'\n{white}--> @{green}username{reset} ')
api = f'https://api.github.com/users/{username}/gists'
response = requests.get(api).json()
if response == []:
print(f'{white}[{red}-{white}]User @{username} does not have any active gists.{reset}')
print(f'\n{white}[{red} - {white}] User ({username}) does not have any active gists.{reset}')
elif "not found" in response['message']:
print(f'\n{white}[{red} - {white}] User ({username}) not found.{reset}')
else:
for item in response:
print(f"\n{white}{item['id']}{reset}")
@@ -317,11 +339,13 @@ class octosuite:
# Fetching user's followera'
def followers(self):
username = input(f'{white}@{green}Username{white} >> {reset}')
username = input(f'\n{white}--> @{green}username{reset} ')
api = f'https://api.github.com/users/{username}/followers?per_page=100'
response = requests.get(api).json()
if response == []:
print(f'\n{white}[{red}-{white}]User @{username} does not have followers.{reset}')
print(f'\n{white}[{red} - {white}]User ({username}) does not have followers.{reset}')
elif "not found" in response['message']:
print(f'\n{white}[{red} - {white}] User ({username}) not found.{reset}')
else:
for item in response:
print(f"\n{white}@{item['login']}{reset}")
@@ -332,19 +356,19 @@ class octosuite:
# Checking whether or not user[A] follows user[B]
def following(self):
user_a = input(f'{white}@{green}User[A]{white} >> {reset}')
user_b = input(f'{white}@{green}User[B]{white} >> {reset}')
user_a = input(f'\n{white}--> @{green}user{white}[A] (username){reset} ')
user_b = input(f'{white}--> @{green}user{white}[B] (username){reset} ')
api = f'https://api.github.com/users/{user_a}/following/{user_b}'
response = requests.get(api)
if response.status_code == 204:
print(f'{white}[{green}+{white}] @{user_a} follows @{user_b}.{reset}')
print(f'\n{white}[{green} + {white}] @{user_a} follows @{user_b}.{reset}')
else:
print(f'{white}[{red}-{white}] @{user_a} does not follow @{user_b}.{reset}')
print(f'\n{white}[{red} - {white}] @{user_a} does not follow @{user_b}.{reset}')
# User search
def user_search(self):
query = input(f'{white}#{green}Query{white} >> {reset}')
query = input(f'\n{white}--> @{green}query{white} (eg. john){reset} ')
api = f'https://api.github.com/search/users?q={query}&per_page=100'
response = requests.get(api).json()
for item in response['items']:
@@ -356,7 +380,7 @@ class octosuite:
# Repository search
def repo_search(self):
query = input(f'{white}#{green}Query{white} >> {reset}')
query = input(f'\n{white}--> %{green}query{white} (eg. git){reset} ')
api = f'https://api.github.com/search/repositories?q={query}&per_page=100'
response = requests.get(api).json()
for item in response['items']:
@@ -368,7 +392,7 @@ class octosuite:
# Topics search
def topic_search(self):
query = input(f'{white}#{green}Query{white} >> {reset}')
query = input(f'\n{white}--> #{green}query{white} (eg. osint){reset} ')
api = f'https://api.github.com/search/topics?q={query}&per_page=100'
response = requests.get(api).json()
for item in response['items']:
@@ -380,7 +404,7 @@ class octosuite:
# Issue search
def issue_search(self):
query = input(f'{white}#{green}Query{white} >> {reset}')
query = input(f'\n{white}--> !{green}query{white} (eg. error){reset} ')
api = f'https://api.github.com/search/issues?q={query}&per_page=100'
response = requests.get(api).json()
for item in response['items']:
@@ -392,40 +416,69 @@ class octosuite:
# Commits search
def commits_search(self):
query = input(f'{white}#{green}Query{white} >> {reset}')
query = input(f'\n{white}--> :{green}query{white} (eg. filename:index.php){reset} ')
api = f'https://api.github.com/search/commits?q={query}&per_page=100'
response = requests.get(api).json()
n=0
number=0
for item in response['items']:
n+=1
print(f'{white}{n}.{reset}')
number+=1
print(f'\n{white}-> {number}.{reset}')
pprint(item['commit'])
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}--> logfile (eg. 2022-04-27 10:09:36.068312.log){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}--> logfile (eg. 2022-04-27 10:09:36.068312.log){reset} ")
with open(f'.logs/{log_file}', 'r') as log:
logging.info(f'Reading log file: {log_file}')
print("\n"+log.read())
# Update program
def update(self):
logging.info('Fetching updates...')
files_to_update = ['src/main.py','lib/banner.py','lib/colors.py','octosuite','.github/dependabot.yml','LICENSE','README.md','requirements.txt']
for file in tqdm(files_to_update,desc=f'{white}[{green}*{white}] Updating{reset}'):
data = urllib.request.urlopen(f'https://raw.githubusercontent.com/rly0nheart/octosuite/master/{file}').read()
logging.info('Updating...')
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}'):
data = requests.get(f'https://raw.githubusercontent.com/rly0nheart/octosuite/master/{file}')
with open(file, 'wb') as code:
code.write(data)
code.write(data.content)
code.close()
logging.info('Update complete.')
exit(f'{white}[{green}+{white}] Updated successfully. Re-run octosuite.{reset}')
exit(f'{white}[{green} + {white}] Update complete. Re-run octosuite.{reset}')
# Show changelog
def changelog(self):
# lol yes the changelog is hard coded
changelog_text = '''
v1.5.0 Changelog:
• Fixed import error in src/main.py
'''
return changelog_text
changelog_text = f'''
{red_bg} {version} [CHANGELOG] {reset}
• Minor bug fixes and improvements
{red_bg} {reset}'''
print(changelog_text)
# Author info
@@ -434,36 +487,56 @@ class octosuite:
for key,value in self.author_dict.items():
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 ({green}exit{reset}{white}) command.{reset}')
# Help/usage
def help(self):
help = '''
help:
help = f'''
Command Descritption
------------ ---------------------------------------------------------
orginfo --> Get target organization info
userinfo --> Get target user profile info
repoinfo --> Get target repository info
pathcontents --> Get contents of a specified path from a target repository
orgrepos --> Get a list of repositories owned by a target organization
userrepos --> Get a list of repositories owned by a target user
usergists --> Get a list of gists owned by a target user
userfollowers --> Get a list of the target's followers
userfollowing --> Check whether or not User[A] follows User[B]
usersearch --> Search user(s)
reposearch --> Search repositor[y][ies]
topicsearch --> Search topic(s)
issuesearch --> Search issue(s)
commitsearch --> Search commit(s)
update --> Update octosuite
changelog --> Show changelog
author --> Show author info
help --> Show usage/help
exit --> Exit session
'''
return help
{red_bg}[COMMAND] [DESCRIPTION] {reset}
info:org Get target organization info
info:user Get target user profile info
info:repo Get target repository info
info:dev Show developer's info
path:contents Get contents of a specified path from a target repository
repos:org Get a list of repositories owned by a target organization
repos:user Get a list of repositories owned by a target user
user:gists Get a list of gists owned by a target user
user:followers Get a list of the target's followers
user:following Check whether or not User[A] follows User[B]
search:users Search user(s)
search:repos Search repositor[y][ies]
search:topics Search topic(s)
search:issues Search issue(s)
search:commits Search commit(s)
logs:view View log files
logs:read Read a specified log file
logs:delete Delete a specified log file
update Update octosuite
changelog Show changelog
help Show usage/help
exit Exit session
{red_bg} {reset}'''
print(help)
# If .logs folder exists, pass
if os.path.exists('.logs'):
pass
else:
# Creating the .logs directory
# 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'])
else:
subprocess.run(['sudo','mkdir','.logs'],shell=False)
# 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',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)