Compare commits
195 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d8b7394f0 | ||
|
|
e925c9cb8a | ||
|
|
dd2edfd204 | ||
|
|
928ba6580f | ||
|
|
457c2a5472 | ||
|
|
c6c037247f | ||
|
|
f84fcf0d35 | ||
|
|
8424c94bec | ||
|
|
a14b356b18 | ||
|
|
f60f088f05 | ||
|
|
c2a5dc89ea | ||
|
|
6a7b61b1f2 | ||
|
|
4427f30f77 | ||
|
|
9982727de1 | ||
|
|
866621db18 | ||
|
|
48b86cb2d0 | ||
|
|
96b10f0bf9 | ||
|
|
53ccc9899b | ||
|
|
bb82427abe | ||
|
|
ee4af7d266 | ||
|
|
3bd6af4f28 | ||
|
|
7531aa4f02 | ||
|
|
f9d56c51a0 | ||
|
|
5bff3ccc12 | ||
|
|
272fcc36ed | ||
|
|
64c1063ea5 | ||
|
|
4c7109f4f0 | ||
|
|
d907167713 | ||
|
|
9eec2e323d | ||
|
|
ead76074f5 | ||
|
|
e87560939f | ||
|
|
3f1191758b | ||
|
|
34c7cd3918 | ||
|
|
52c4101a7a | ||
|
|
0677b901f7 | ||
|
|
49215fd03e | ||
|
|
8fc14d3ec4 | ||
|
|
3da2b91fb2 | ||
|
|
b6908a19f4 | ||
|
|
4db8300e2c | ||
|
|
07ca8c486c | ||
|
|
9473b0278d | ||
|
|
4113c62d09 | ||
|
|
f235bc1186 | ||
|
|
4d0e7beea7 | ||
|
|
7b1fd3addc | ||
|
|
3968f53e98 | ||
|
|
bd9c1f210f | ||
|
|
0518f33571 | ||
|
|
c783a717a0 | ||
|
|
ea3b8bcd71 | ||
|
|
cdf04fe443 | ||
|
|
f3b90f2e6d | ||
|
|
bf77bc4dfe | ||
|
|
157cb68142 | ||
|
|
53433c119b | ||
|
|
5d41e07bc2 | ||
|
|
331c81ac46 | ||
|
|
e3c151e2d3 | ||
|
|
a89596efc2 | ||
|
|
283a92fa84 | ||
|
|
beb8d561f8 | ||
|
|
b68842df1c | ||
|
|
dd7fcc455d | ||
|
|
b3ae15a062 | ||
|
|
4c8d3626b3 | ||
|
|
1f86ad4034 | ||
|
|
e151f81d76 | ||
|
|
a69fbf33d9 | ||
|
|
227fcd0482 | ||
|
|
8d04112d32 | ||
|
|
66373fd96e | ||
|
|
c4f1940bb6 | ||
|
|
f79813ed45 | ||
|
|
ffd162d881 | ||
|
|
558715fdab | ||
|
|
9984c71a57 | ||
|
|
bb2efb903b | ||
|
|
defe1b1159 | ||
|
|
347acea797 | ||
|
|
46937abb7e | ||
|
|
2963db3608 | ||
|
|
92d4f3f9f2 | ||
|
|
02df05df39 | ||
|
|
549f1940f9 | ||
|
|
e936525f81 | ||
|
|
29eb2bde95 | ||
|
|
d27d9b9168 | ||
|
|
a6ca1e3c0c | ||
|
|
5bf7ef3f39 | ||
|
|
ae73fdffde | ||
|
|
7c8fea02e6 | ||
|
|
40fffcab73 | ||
|
|
9a6127d6bc | ||
|
|
eb724f629f | ||
|
|
6d04b990db | ||
|
|
2537bcbab8 | ||
|
|
bb6c5a09e9 | ||
|
|
083d3e9f71 | ||
|
|
497c855648 | ||
|
|
c2641b3134 | ||
|
|
a108b4784e | ||
|
|
597ad07490 | ||
|
|
94c1e0a737 | ||
|
|
6e83bcf367 | ||
|
|
a57f5d47e2 | ||
|
|
3fa3e7a182 | ||
|
|
d42b7af59f | ||
|
|
8d337c621c | ||
|
|
5842a13975 | ||
|
|
e739f78eb9 | ||
|
|
26cf25bf91 | ||
|
|
ad6959d1b9 | ||
|
|
d7af8602fe | ||
|
|
29d40ec27e | ||
|
|
6a0953401b | ||
|
|
e87e5c64c8 | ||
|
|
c53ab2a00b | ||
|
|
b30ad16719 | ||
|
|
cfa032f7cb | ||
|
|
87f287bfb9 | ||
|
|
ab70a10d19 | ||
|
|
02e19baa93 | ||
|
|
0b76846968 | ||
|
|
9614785455 | ||
|
|
6ae34437a4 | ||
|
|
5a1b5378ee | ||
|
|
64d1b6bf38 | ||
|
|
09fffdf192 | ||
|
|
8e4520b6d2 | ||
|
|
420186bec4 | ||
|
|
758676ac88 | ||
|
|
310b1fb702 | ||
|
|
6822806a77 | ||
|
|
4eddd20480 | ||
|
|
95dcfbea6e | ||
|
|
258be0a2d7 | ||
|
|
3b329d039a | ||
|
|
fec88ac343 | ||
|
|
272cd49d0e | ||
|
|
cea07f187a | ||
|
|
0f96785123 | ||
|
|
000eb80fbc | ||
|
|
e4f1e2928a | ||
|
|
73fa406e82 | ||
|
|
e99e0c317e | ||
|
|
7d2eada3f9 | ||
|
|
f706a08859 | ||
|
|
b3ccb713e1 | ||
|
|
0bb330d771 | ||
|
|
df339d33df | ||
|
|
c296f09e0e | ||
|
|
04ea880276 | ||
|
|
eef44716d5 | ||
|
|
8eea84e546 | ||
|
|
acd65e7919 | ||
|
|
4a7b199929 | ||
|
|
2723e75735 | ||
|
|
0365616478 | ||
|
|
befd61eea0 | ||
|
|
daa426d73b | ||
|
|
22df1eae73 | ||
|
|
51c1efbcec | ||
|
|
d091125c15 | ||
|
|
e2c94fcc89 | ||
|
|
16f9a80818 | ||
|
|
66d7a2c42c | ||
|
|
456d46fdb1 | ||
|
|
539c540a72 | ||
|
|
db413767cd | ||
|
|
6a87cb51de | ||
|
|
f98bfb34f3 | ||
|
|
43637193de | ||
|
|
33d9c7f5f2 | ||
|
|
835a78284b | ||
|
|
4dc2dced32 | ||
|
|
4b18c0307e | ||
|
|
0ec3100347 | ||
|
|
bb287acfe2 | ||
|
|
7a6015b8e4 | ||
|
|
d0f5c660b5 | ||
|
|
2e65cfcb79 | ||
|
|
41f392f5a0 | ||
|
|
18bcc06070 | ||
|
|
c9cf000b23 | ||
|
|
11e55f7804 | ||
|
|
96c62c7097 | ||
|
|
587641cd18 | ||
|
|
d1ad3d14b9 | ||
|
|
0e3568f967 | ||
|
|
51d27c4996 | ||
|
|
ae9d9f4af5 | ||
|
|
482f2ee55a | ||
|
|
9894b15209 | ||
|
|
4d563683d2 |
72
.github/workflows/codeql.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# For most projects, this workflow file will not need changing; you simply need
|
||||||
|
# to commit it to your repository.
|
||||||
|
#
|
||||||
|
# You may wish to alter this file to override the set of languages analyzed,
|
||||||
|
# or to provide custom queries or build logic.
|
||||||
|
#
|
||||||
|
# ******** NOTE ********
|
||||||
|
# We have attempted to detect the languages in your repository. Please check
|
||||||
|
# the `language` matrix defined below to confirm you have the correct set of
|
||||||
|
# supported CodeQL languages.
|
||||||
|
#
|
||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ "master" ]
|
||||||
|
schedule:
|
||||||
|
- cron: '18 7 * * 3'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'python' ]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
|
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
|
||||||
|
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||||
|
# queries: security-extended,security-and-quality
|
||||||
|
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
|
|
||||||
|
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||||
|
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||||
|
|
||||||
|
# - run: |
|
||||||
|
# echo "Run, Build Application using script"
|
||||||
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
__pycache__/
|
||||||
11
Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
FROM python:latest
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN pip install --upgrade pip && pip install build && python -m build && pip install dist/*.whl
|
||||||
|
|
||||||
|
ENTRYPOINT ["octosuite"]
|
||||||
48
README.md
@@ -1,14 +1,23 @@
|
|||||||

|

|
||||||
|
|
||||||

|
A framework for gathering open-source intelligence on GitHub users, repositories and organizations
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
> *Simply gather OSINT on Github users & organizations like a God🔥*
|
[](https://github.com/bellingcat/octosuite/actions/workflows/python-publish.yml)
|
||||||
|
[](https://github.com/bellingcat/octosuite/actions/workflows/codeql.yml)
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
# Installation
|
|
||||||
[Refer to the Wiki](https://github.com/rly0nheart/octosuite/wiki) for installation instructions, in addition to all other documentation.
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
# Wiki
|
||||||
|
[Refer to the Wiki](https://github.com/bellingcat/octosuite/wiki) for installation instructions, in addition to all other documentation.
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
- [x] Fetches an organization's profile information
|
- [x] Fetches an organization's profile information
|
||||||
@@ -40,26 +49,19 @@
|
|||||||
- [x] Searches commits
|
- [x] Searches commits
|
||||||
- [x] Automatically logs network activity (.logs folder)
|
- [x] Automatically logs network activity (.logs folder)
|
||||||
- [x] User can view, read and delete logs
|
- [x] User can view, read and delete logs
|
||||||
- [x] More available...
|
- [x] All the above can be used with command-line arguments (PyPI Package only)
|
||||||
|
- [x] ...And more
|
||||||
|
|
||||||
|
## Note
|
||||||
|
> Octosuite automatically logs network and user activity of each session, the logs are saved by date and time in the .logs folder
|
||||||
|
|
||||||
> *octosuite automatically logs network and minor user activity of each session. The logs are saved by date and time in the .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* ✌🏾🙂
|
|
||||||
|
|
||||||
# License
|
# License
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
# About developer
|
|
||||||
[About.me](https://about.me/rly0nheart)
|
|
||||||
|
|
||||||
|
|
||||||
# Supporters
|
|
||||||
[](https://github.com/rly0nheart/octosuite/stargazers)
|
|
||||||
[](https://github.com/rly0nheart/octosuite/members)
|
|
||||||
|
|
||||||
|
|
||||||
# Donations
|
# Donations
|
||||||
Love octosuite? Please consider buying me a coffee, I will really appreciate it. ☕👌🏾😊
|
If you like OctoSuite and would like to show support, you can Buy A Coffee for the developer using the button below
|
||||||
|
|
||||||
<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>
|
<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>
|
||||||
|
|
||||||
|
Your support will be much appreciated😊
|
||||||
|
|||||||
BIN
images/octosuite_app.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
images/octosuite_app1.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
images/octosuite_exe.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
images/octosuite_gui_exe (1).png
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
images/octosuite_gui_exe (2).png
Normal file
|
After Width: | Height: | Size: 264 KiB |
BIN
images/octosuite_gui_exe (3).png
Normal file
|
After Width: | Height: | Size: 257 KiB |
BIN
images/octosuite_gui_exe (4).png
Normal file
|
After Width: | Height: | Size: 234 KiB |
BIN
images/octosuite_gui_exe.png
Normal file
|
After Width: | Height: | Size: 207 KiB |
@@ -1,23 +1,23 @@
|
|||||||
import getpass
|
import getpass
|
||||||
from octosuite.colors import Color
|
from octosuite.config import red, white, green, reset, Tree
|
||||||
|
|
||||||
'''
|
|
||||||
Banner
|
# banner.py
|
||||||
This class holds the program's banner logo and version tag
|
# This file holds the program's banner and version tag
|
||||||
'''
|
version_tag = "3.0.0"
|
||||||
class Banner:
|
|
||||||
versionTag = '2.1.0'
|
|
||||||
nameLogo = f'''{Color.white}
|
def banner():
|
||||||
|
banner_tree = Tree(getpass.getuser())
|
||||||
|
banner_tree.add(f"use ‘{green}help{reset}’ command for usage")
|
||||||
|
banner_tree.add(f"commands are case insensitive\n")
|
||||||
|
return f"""
|
||||||
_______ __ _______ __ __
|
_______ __ _______ __ __
|
||||||
| |.----.| |_.-----.| __|.--.--.|__| |_.-----.
|
| |.----.| |_.-----.| __|.--.--.|__| |_.-----.
|
||||||
| - || __|| _| _ ||__ || | || | _| -__|
|
| - || __|| _| _ ||__ || | || | _| -__|
|
||||||
|_______||____||____|_____||_______||_____||__|____|_____|
|
|_______||____||____|_____||_______||_____||__|____|_____|
|
||||||
v{versionTag}
|
v{version_tag}#dev
|
||||||
{Color.white}— Advanced Github {Color.red}OSINT{Color.white} Framework{Color.reset}
|
{white}— Advanced Github {red}OSINT{white} Framework
|
||||||
|
|
||||||
|
|
||||||
|
""", banner_tree
|
||||||
.:{getpass.getuser()}:.
|
|
||||||
{Color.white}├─ use {Color.green}help{Color.reset}{Color.white} command for usage{Color.reset}
|
|
||||||
{Color.white}└╼ commands are case insensitive{Color.reset}
|
|
||||||
'''
|
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
import sys
|
|
||||||
import platform
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
# The Color class is responsible for enabling/disabling colors in OctoSuite
|
|
||||||
# This class gets called first at start up before any other class/method gets called (makes one think why this is not the firstBlood class)
|
|
||||||
# Color class is the reason why users get to choose whether to enable/disable colors
|
|
||||||
# Unfortunately for our friends the 'non-Linux' users, they will not yet have the opportunity to see what OctoSuite looks like with colors enabled lol
|
|
||||||
class Color:
|
|
||||||
colors = True
|
|
||||||
# Colors will be unavailable on non-linux machines
|
|
||||||
if sys.platform.lower().startswith(("os", "win", "darwin","ios")):
|
|
||||||
colors = False
|
|
||||||
|
|
||||||
if not colors:
|
|
||||||
reset = red = white = green = red_bg = ""
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Printing system information was completely unnecessary (just like most things in this program :D)
|
|
||||||
# But at least users will get to know things they did not know about their machines ;)
|
|
||||||
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, 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"
|
|
||||||
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].")
|
|
||||||
200
octosuite/config.py
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
import psutil
|
||||||
|
import platform
|
||||||
|
import argparse
|
||||||
|
from rich.tree import Tree
|
||||||
|
from rich.text import Text
|
||||||
|
from rich.table import Table
|
||||||
|
from datetime import datetime
|
||||||
|
from rich import print as xprint
|
||||||
|
from rich.prompt import Prompt, Confirm
|
||||||
|
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
return """
|
||||||
|
Basic Usage
|
||||||
|
===========
|
||||||
|
|
||||||
|
Get User Profile Info
|
||||||
|
---------------------
|
||||||
|
octosuite --method user_profile --username <username>
|
||||||
|
|
||||||
|
|
||||||
|
Get User Repos
|
||||||
|
--------------
|
||||||
|
octosuite --method user_repos --username <username>
|
||||||
|
|
||||||
|
|
||||||
|
Get Organi[sz]ation Profile Info
|
||||||
|
-----------------------------
|
||||||
|
octosuite --method org_profile --organization <organization_name>
|
||||||
|
|
||||||
|
|
||||||
|
Get Organi[sz]ation Repos
|
||||||
|
-----------------------------
|
||||||
|
octosuite --method org_repos --organization <organization_name>
|
||||||
|
|
||||||
|
|
||||||
|
Get Repo Profile Info
|
||||||
|
---------------------
|
||||||
|
octosuite --method repo_profile --username <username> --repository <repo_name>
|
||||||
|
|
||||||
|
|
||||||
|
Get Repo Forks
|
||||||
|
--------------
|
||||||
|
octosuite --method repo_forks --username <username> --repository <repo_name>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Searching
|
||||||
|
=========
|
||||||
|
|
||||||
|
Search Users
|
||||||
|
------------
|
||||||
|
octosuite --method users_search --query <query>
|
||||||
|
|
||||||
|
|
||||||
|
Search Issues
|
||||||
|
-------------
|
||||||
|
octosuite --method issues_search --query <query>
|
||||||
|
|
||||||
|
|
||||||
|
Search Commits
|
||||||
|
--------------
|
||||||
|
octosuite --method commits_search --query <query>
|
||||||
|
|
||||||
|
|
||||||
|
Search Topics
|
||||||
|
-------------
|
||||||
|
octosuite --method topics_search --query <query>
|
||||||
|
|
||||||
|
|
||||||
|
Search Repositories
|
||||||
|
-------------------
|
||||||
|
octosuite --method repos_search --query <query>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Log Management
|
||||||
|
==============
|
||||||
|
|
||||||
|
View logs
|
||||||
|
---------
|
||||||
|
octosuite --method view_logs
|
||||||
|
|
||||||
|
|
||||||
|
Read log
|
||||||
|
--------
|
||||||
|
octosuite --method read_log --log-file <log_file>
|
||||||
|
|
||||||
|
|
||||||
|
Delete log
|
||||||
|
----------
|
||||||
|
octosuite --method delete_log --log-file <log_file>
|
||||||
|
|
||||||
|
|
||||||
|
Clear logs
|
||||||
|
----------
|
||||||
|
octosuite --method clear_logs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CSV Management
|
||||||
|
==============
|
||||||
|
|
||||||
|
View CSV
|
||||||
|
---------
|
||||||
|
octosuite --method view_csv
|
||||||
|
|
||||||
|
|
||||||
|
Read CSV
|
||||||
|
--------
|
||||||
|
octosuite --method read_csv --csv-file <csv_file>
|
||||||
|
|
||||||
|
|
||||||
|
Delete CSV
|
||||||
|
----------
|
||||||
|
octosuite --method delete_csv --csv-file <csv_file>
|
||||||
|
|
||||||
|
|
||||||
|
Clear CSV's
|
||||||
|
-----------
|
||||||
|
octosuite --method clear_csv
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def create_parser():
|
||||||
|
parser = argparse.ArgumentParser(description='OCTOSUITE: Advanced GitHub osint framework — by Richard Mwewa | https://about.me/rly0nheart', usage=usage())
|
||||||
|
parser.add_argument('-m', '--method', help='method', choices=['user_profile', 'user_repos', 'user_gists', 'user_orgs', 'user_events',
|
||||||
|
'user_subscriptions', 'user_following', 'user_followers', 'user_follows',
|
||||||
|
'org_profile', 'org_repos', 'org_events', 'org_member',
|
||||||
|
'repo_profile', 'repo_contributors', 'repo_stargazers', 'repo_forks',
|
||||||
|
'repo_issues', 'repo_releases', 'repo_path_contents', 'users_search', 'issues_search',
|
||||||
|
'commits_search', 'topics_search', 'repos_search', 'view_logs', 'read_log', 'delete_log',
|
||||||
|
'clear_logs', 'view_csv', 'read_csv', 'delete_csv', 'clear_csv', 'about', 'author'])
|
||||||
|
parser.add_argument('-u', '--username', help='username')
|
||||||
|
parser.add_argument('-uB', '--username_b', help='username_B (used with user_follows)')
|
||||||
|
parser.add_argument('-o', '--organization', '--organisation', help='organi[sz]ation name')
|
||||||
|
parser.add_argument('-r', '--repository', help='repository name')
|
||||||
|
parser.add_argument('-p', '--path_name', help='path name (used with repo_path_contents)')
|
||||||
|
parser.add_argument('-q', '--query', help='query (used with search methods)')
|
||||||
|
parser.add_argument('-l', '--limit', help='output limit (used with methods that return results in bulk) (default: %(default)s)', default=10)
|
||||||
|
parser.add_argument('-c', '--colors', '--colours', help='specify to run octosuite cli with colo[u]rs enabled', action='store_true')
|
||||||
|
parser.add_argument('--csv_file', help='csv file (used with csv management methods)')
|
||||||
|
parser.add_argument('--log_file', help='log file (used with logs management methods)')
|
||||||
|
parser.add_argument('--log-to-csv', help='log output to a csv file', action='store_true', dest='log_csv')
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
parser = create_parser()
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# This file is responsible for enabling/disabling colo[u]rs and configuring argparse in OctoSuite
|
||||||
|
# This file gets called first at start up before any other file
|
||||||
|
# config.py is the reason why users get to choose whether to enable/disable colo[u]rs, and call the program with command line arguments
|
||||||
|
# delete this file (I dare you), the entire program breaks
|
||||||
|
system_info = [("RAM", f"{str(round(psutil.virtual_memory().total / (1024.0 ** 3)))}GB"),
|
||||||
|
("Node", platform.node()),
|
||||||
|
("Release", platform.release()),
|
||||||
|
("Version", platform.version()),
|
||||||
|
("Processor", platform.processor()),
|
||||||
|
("Architecture", platform.architecture())]
|
||||||
|
first_banner = f"""
|
||||||
|
OCTOSUITE © 2023 Richard Mwewa
|
||||||
|
{datetime.now().strftime('%A %d %B %Y, %H:%M:%S%p')}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if args.colors:
|
||||||
|
header_title = "bold white"
|
||||||
|
red = "[red]"
|
||||||
|
white = "[white]"
|
||||||
|
green = "[green]"
|
||||||
|
yellow = "[yellow]"
|
||||||
|
red_bold = "[white bold]"
|
||||||
|
white_bold = "[white bold]"
|
||||||
|
green_bold = "[green bold]"
|
||||||
|
reset = "[/]"
|
||||||
|
else:
|
||||||
|
print(first_banner)
|
||||||
|
system_tree = Tree(platform.system())
|
||||||
|
for system_key, system_value in system_info:
|
||||||
|
system_tree.add(f"{system_key}: {system_value}")
|
||||||
|
xprint(system_tree)
|
||||||
|
print("\n")
|
||||||
|
try:
|
||||||
|
color_chooser = Confirm.ask(f"Welcome, would you like to enable colo(u)rs for this session?")
|
||||||
|
if color_chooser:
|
||||||
|
header_title = "bold white"
|
||||||
|
red = "[red]"
|
||||||
|
white = "[white]"
|
||||||
|
green = "[green]"
|
||||||
|
yellow = "[yellow]"
|
||||||
|
red_bold = "[white bold]"
|
||||||
|
white_bold = "[white bold]"
|
||||||
|
green_bold = "[green bold]"
|
||||||
|
reset = "[/]"
|
||||||
|
else:
|
||||||
|
header_title = red = white = green = red_bold = white_bold = green_bold = reset = yellow = ""
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
exit(f"[WARNING] Process interrupted with Ctrl+C.")
|
||||||
|
|
||||||
@@ -1,446 +1,442 @@
|
|||||||
|
import os
|
||||||
import csv
|
import csv
|
||||||
import sys
|
|
||||||
import logging
|
import logging
|
||||||
from octosuite.sign_vars import SignVar
|
from rich import print as xprint
|
||||||
from octosuite.log_roller import logRoller
|
from octosuite.log_roller import prompt_log_csv, logged_to_csv
|
||||||
|
from octosuite.message_prefixes import PROMPT, WARNING, POSITIVE, NEGATIVE, INFO
|
||||||
'''
|
|
||||||
csvLogger
|
|
||||||
This class holds the methods for creating .csv files of each functionality in main
|
# csv_loggers.py
|
||||||
'''
|
# This file holds the functions for creating .csv files of each functionality in main
|
||||||
class csvLogger:
|
def log_org_profile(response):
|
||||||
# .csv for organization' profile
|
org_profile_fields = ['Profile photo', 'Name', 'Username', 'ID', 'Node ID', 'Email', 'About', 'Location', 'Blog',
|
||||||
def logOrgProfile(response):
|
'Followers', 'Following', 'Twitter handle', 'Gists', 'Repositories', 'Account type',
|
||||||
org_profile_fields = ['Profile photo', 'Name', 'Username', 'ID', 'Node ID', 'Email', 'About', 'Location', 'Blog', 'Followers', 'Following', 'Twitter handle', 'Gists', 'Repositories', 'Account type', 'Is verified?', 'Has organization projects?', 'Has repository projects?', 'Created at', 'Updated at']
|
'Is verified?', 'Has organization projects?', 'Has repository projects?', 'Created at',
|
||||||
org_profile_row = [response.json()['avatar_url'], response.json()['name'], response.json()['login'], response.json()['id'], response.json()['node_id'], response.json()['email'], response.json()['description'], response.json()['location'], response.json()['blog'], response.json()['followers'], response.json()['following'], response.json()['twitter_username'], response.json()['public_gists'], response.json()['public_repos'], response.json()['type'], response.json()['is_verified'], response.json()['has_organization_projects'], response.json()['has_repository_projects'], response.json()['created_at'], response.json()['updated_at']]
|
'Updated at']
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
org_profile_row = [response.json()['avatar_url'], response.json()['name'], response.json()['login'],
|
||||||
if prompt == 'y':
|
response.json()['id'], response.json()['node_id'], response.json()['email'],
|
||||||
with open(f"output/{response.json()['name']}.csv", 'w') as file:
|
response.json()['description'], response.json()['location'], response.json()['blog'],
|
||||||
writecsv = csv.writer(file)
|
response.json()['followers'], response.json()['following'], response.json()['twitter_username'],
|
||||||
writecsv.writerow(org_profile_fields)
|
response.json()['public_gists'], response.json()['public_repos'], response.json()['type'],
|
||||||
writecsv.writerow(org_profile_row)
|
response.json()['is_verified'], response.json()['has_organization_projects'],
|
||||||
|
response.json()['has_repository_projects'], response.json()['created_at'],
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
response.json()['updated_at']]
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
|
||||||
|
with open(os.path.join("output", f"{response.json()['name']}.csv"), 'w') as file:
|
||||||
else:
|
write_csv = csv.writer(file)
|
||||||
logging.info(logRoller.loggingSkipped)
|
write_csv.writerow(org_profile_fields)
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
write_csv.writerow(org_profile_row)
|
||||||
|
|
||||||
|
logging.info(logged_to_csv.format(file.name))
|
||||||
# Creating a .csv file of a user' profile
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
def logUserProfile(response):
|
|
||||||
user_profile_fields = ['Profile photo', 'Name', 'Username', 'ID', 'Node ID', 'Bio', 'Blog', 'Location', 'Followers', 'Following', 'Twitter handle', 'Gists', 'Repositories', 'Organization', 'Is hireable?', 'Is site admin?', 'Joined at', 'Updated at']
|
|
||||||
user_profile_row = [response.json()['avatar_url'], response.json()['name'], response.json()['login'], response.json()['id'], response.json()['node_id'], response.json()['bio'], response.json()['blog'], response.json()['location'], response.json()['followers'], response.json()['following'], response.json()['twitter_username'], response.json()['public_gists'], response.json()['public_repos'], response.json()['company'], response.json()['hireable'], response.json()['site_admin'], response.json()['created_at'], response.json()['updated_at']]
|
# Creating a .csv file of a user' profile
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
def log_user_profile(response):
|
||||||
if prompt == 'y':
|
user_profile_fields = ['Profile photo', 'Name', 'Username', 'ID', 'Node ID', 'Bio', 'Blog', 'Location', 'Followers',
|
||||||
with open(f"output/{response.json()['login']}.csv", 'w',) as file:
|
'Following', 'Twitter handle', 'Gists', 'Repositories', 'Organization', 'Is hireable?',
|
||||||
writecsv = csv.writer(file)
|
'Is site admin?', 'Joined at', 'Updated at']
|
||||||
writecsv.writerow(user_profile_fields)
|
user_profile_row = [response.json()['avatar_url'], response.json()['name'], response.json()['login'],
|
||||||
writecsv.writerow(user_profile_row)
|
response.json()['id'], response.json()['node_id'], response.json()['bio'],
|
||||||
|
response.json()['blog'], response.json()['location'], response.json()['followers'],
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
response.json()['following'], response.json()['twitter_username'],
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
response.json()['public_gists'], response.json()['public_repos'], response.json()['company'],
|
||||||
|
response.json()['hireable'], response.json()['site_admin'], response.json()['created_at'],
|
||||||
else:
|
response.json()['updated_at']]
|
||||||
logging.info(logRoller.loggingSkipped)
|
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
with open(os.path.join("output", f"{response.json()['login']}.csv"), 'w') as file:
|
||||||
|
write_csv = csv.writer(file)
|
||||||
|
write_csv.writerow(user_profile_fields)
|
||||||
# create .csv for repository profile
|
write_csv.writerow(user_profile_row)
|
||||||
def logRepoProfile(response):
|
|
||||||
repo_profile_fields = [ 'Name','ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility', 'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?', 'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?', 'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
logging.info(logged_to_csv.format(file.name))
|
||||||
repo_profile_row = [response.json()['name'], response.json()['id'], response.json()['description'], response.json()['forks'], response.json()['stargazers_count'], response.json()['watchers'], response.json()['license'], response.json()['default_branch'], response.json()['visibility'], response.json()['language'], response.json()['open_issues'], response.json()['topics'], response.json()['homepage'], response.json()['clone_url'], response.json()['ssh_url'], response.json()['fork'], response.json()['allow_forking'], response.json()['private'], response.json()['archived'], response.json()['is_template'], response.json()['has_wiki'], response.json()['has_pages'], response.json()['has_projects'], response.json()['has_issues'], response.json()['has_downloads'], response.json()['pushed_at'], response.json()['created_at'], response.json()['updated_at']]
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
|
||||||
if prompt == 'y':
|
|
||||||
with open(f"output/{response.json()['name']}.csv", 'w') as file:
|
# create .csv for repository profile
|
||||||
writecsv = csv.writer(file)
|
def log_repo_profile(response):
|
||||||
writecsv.writerow(repo_profile_fields)
|
repo_profile_fields = ['Name', 'ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility',
|
||||||
writecsv.writerow(repo_profile_row)
|
'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?',
|
||||||
|
'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?',
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
repo_profile_row = [response.json()['name'], response.json()['id'], response.json()['description'],
|
||||||
|
response.json()['forks'], response.json()['stargazers_count'], response.json()['watchers'],
|
||||||
else:
|
response.json()['license'], response.json()['default_branch'], response.json()['visibility'],
|
||||||
logging.info(logRoller.loggingSkipped)
|
response.json()['language'], response.json()['open_issues'], response.json()['topics'],
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
response.json()['homepage'], response.json()['clone_url'], response.json()['ssh_url'],
|
||||||
|
response.json()['fork'], response.json()['allow_forking'], response.json()['private'],
|
||||||
|
response.json()['archived'], response.json()['is_template'], response.json()['has_wiki'],
|
||||||
# create .csv for repository path contents
|
response.json()['has_pages'], response.json()['has_projects'], response.json()['has_issues'],
|
||||||
def logRepoPathContents(content, repo_name):
|
response.json()['has_downloads'], response.json()['pushed_at'], response.json()['created_at'],
|
||||||
path_content_fields = ['Filename', 'Size (bytes)', 'Type', 'Path', 'SHA', 'URL']
|
response.json()['updated_at']]
|
||||||
path_content_row = [content['name'], content['size'], content['type'], content['path'], content['sha'], content['html_url']]
|
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
with open(os.path.join("output", f"{response.json()['name']}.csv"), 'w') as file:
|
||||||
if prompt == 'y':
|
write_csv = csv.writer(file)
|
||||||
with open(f"output/{content['name']}_content_from_{repo_name}.csv", 'w') as file:
|
write_csv.writerow(repo_profile_fields)
|
||||||
writecsv = csv.writer(file)
|
write_csv.writerow(repo_profile_row)
|
||||||
writecsv.writerow(path_content_fields)
|
|
||||||
writecsv.writerow(path_content_row)
|
logging.info(logged_to_csv.format(file.name))
|
||||||
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
|
||||||
|
# create .csv for repository path contents
|
||||||
else:
|
def log_repo_path_contents(content, repo_name):
|
||||||
logging.info(logRoller.loggingSkipped)
|
path_content_fields = ['Filename', 'Size (bytes)', 'Type', 'Path', 'SHA', 'URL']
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
path_content_row = [content['name'], content['size'], content['type'], content['path'], content['sha'],
|
||||||
|
content['html_url']]
|
||||||
|
|
||||||
# create .csv for repository stargazer
|
with open(os.path.join("output", f"{content['name']}_content_from_{repo_name}.csv"), 'w') as file:
|
||||||
def logRepoStargazers(stargazer, repo_name):
|
write_csv = csv.writer(file)
|
||||||
user_follower_fields = ['Profile photo', 'Username', 'ID', 'Node ID', 'Gravatar ID', 'Account type', 'Is site admin?', 'URL']
|
write_csv.writerow(path_content_fields)
|
||||||
user_follower_row = [stargazer['avatar_url'], stargazer['login'], stargazer['id'], stargazer['node_id'], stargazer['gravatar_id'], stargazer['type'], stargazer['site_admin'], stargazer['html_url']]
|
write_csv.writerow(path_content_row)
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
|
||||||
if prompt == 'y':
|
logging.info(logged_to_csv.format(file.name))
|
||||||
with open(f"output/{stargazer['login']}_stargazer_of_{repo_name}.csv", 'w') as file:
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
writecsv = csv.writer(file)
|
|
||||||
writecsv.writerow(user_follower_fields)
|
|
||||||
writecsv.writerow(user_follower_row)
|
# create .csv for repository stargazer
|
||||||
|
def log_repo_stargazers(stargazer, repo_name):
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
user_follower_fields = ['Profile photo', 'Username', 'ID', 'Node ID', 'Gravatar ID', 'Account type',
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
'Is site admin?', 'URL']
|
||||||
|
user_follower_row = [stargazer['avatar_url'], stargazer['login'], stargazer['id'], stargazer['node_id'],
|
||||||
else:
|
stargazer['gravatar_id'], stargazer['type'], stargazer['site_admin'], stargazer['html_url']]
|
||||||
logging.info(logRoller.loggingSkipped)
|
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
with open(os.path.join("output", f"{stargazer['login']}_stargazer_of_{repo_name}.csv"), 'w') as file:
|
||||||
|
write_csv = csv.writer(file)
|
||||||
|
write_csv.writerow(user_follower_fields)
|
||||||
# create .csv for repository forks
|
write_csv.writerow(user_follower_row)
|
||||||
def logRepoForks(fork, count):
|
|
||||||
repo_fork_fields = [ 'Name','ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility', 'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?', 'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?', 'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
logging.info(logged_to_csv.format(file.name))
|
||||||
repo_fork_row = [fork['full_name'], fork['id'], fork['description'], fork['forks'], fork['stargazers_count'], fork['watchers'], fork['license'], fork['default_branch'], fork['visibility'], fork['language'], fork['open_issues'], fork['topics'], fork['homepage'], fork['clone_url'], fork['ssh_url'], fork['fork'], fork['allow_forking'], fork['private'], fork['archived'], fork['is_template'], fork['has_wiki'], fork['has_pages'], fork['has_projects'], fork['has_issues'], fork['has_downloads'], fork['pushed_at'], fork['created_at'], fork['updated_at']]
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
|
||||||
if prompt == 'y':
|
# create .csv for repository forks
|
||||||
with open(f"output/{fork['name']}_fork_{count}.csv", 'w') as file:
|
def log_repo_forks(fork, count):
|
||||||
writecsv = csv.writer(file)
|
repo_fork_fields = ['Name', 'ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility',
|
||||||
writecsv.writerow(repo_fork_fields)
|
'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?',
|
||||||
writecsv.writerow(repo_fork_row)
|
'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?',
|
||||||
|
'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
repo_fork_row = [fork['full_name'], fork['id'], fork['description'], fork['forks'], fork['stargazers_count'],
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
fork['watchers'], fork['license'], fork['default_branch'], fork['visibility'], fork['language'],
|
||||||
|
fork['open_issues'], fork['topics'], fork['homepage'], fork['clone_url'], fork['ssh_url'],
|
||||||
else:
|
fork['fork'], fork['allow_forking'], fork['private'], fork['archived'], fork['is_template'],
|
||||||
logging.info(logRoller.loggingSkipped)
|
fork['has_wiki'], fork['has_pages'], fork['has_projects'], fork['has_issues'],
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
fork['has_downloads'], fork['pushed_at'], fork['created_at'], fork['updated_at']]
|
||||||
|
|
||||||
|
with open(os.path.join("output", f"{fork['name']}_fork_{count}.csv"), 'w') as file:
|
||||||
# create .csv for repository issues
|
write_csv = csv.writer(file)
|
||||||
def logRepoIssues(issue, repo_name):
|
write_csv.writerow(repo_fork_fields)
|
||||||
repo_issue_fields = ['Title', 'ID', 'Node ID', 'Number', 'State', 'Reactions', 'Comments', 'Milestone', 'Assignee', 'Assignees', 'Author association', 'Labels', 'Is locked?', 'Lock reason', 'Closed at', 'Created at', 'Updated at']
|
write_csv.writerow(repo_fork_row)
|
||||||
repo_issue_row = [issue['title'], issue['id'], issue['node_id'], issue['number'], issue['state'], issue['reactions'], issue['comments'], issue['milestone'], issue['assignee'], issue['assignees'], issue['author_association'], issue['labels'], issue['locked'], issue['active_lock_reason'], issue['closed_at'], issue['created_at'], issue['updated_at']]
|
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
logging.info(logged_to_csv.format(file.name))
|
||||||
if prompt == 'y':
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
with open(f"output/{repo_name}_issue_{issue['id']}.csv", 'w') as file:
|
|
||||||
writecsv = csv.writer(file)
|
|
||||||
writecsv.writerow(repo_issue_fields)
|
# create .csv for repository issues
|
||||||
writecsv.writerow(repo_issue_row)
|
def log_repo_issues(issue, repo_name):
|
||||||
|
repo_issue_fields = ['Title', 'ID', 'Node ID', 'Number', 'State', 'Reactions', 'Comments', 'Milestone', 'Assignee',
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
'Assignees', 'Author association', 'Labels', 'Is locked?', 'Lock reason', 'Closed at',
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
'Created at', 'Updated at']
|
||||||
|
repo_issue_row = [issue['title'], issue['id'], issue['node_id'], issue['number'], issue['state'],
|
||||||
else:
|
issue['reactions'], issue['comments'], issue['milestone'], issue['assignee'], issue['assignees'],
|
||||||
logging.info(logRoller.loggingSkipped)
|
issue['author_association'], issue['labels'], issue['locked'], issue['active_lock_reason'],
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
issue['closed_at'], issue['created_at'], issue['updated_at']]
|
||||||
|
|
||||||
|
with open(os.path.join("output", f"{repo_name}_issue_{issue['id']}.csv"), 'w') as file:
|
||||||
# create .csv for repository releases
|
write_csv = csv.writer(file)
|
||||||
def logRepoReleases(release, repo_name):
|
write_csv.writerow(repo_issue_fields)
|
||||||
repo_release_fields = ['Name', 'ID', 'Node ID', 'Tag', 'Branch', 'Assets', 'Is draft?', 'Is prerelease?', 'Created at', 'Published at']
|
write_csv.writerow(repo_issue_row)
|
||||||
repo_release_row = [release['name'], release['id'], release['node_id'], release['tag_name'], release['target_commitish'], release['assets'], release['draft'], release['prerelease'], release['created_at'], release['published_at']]
|
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
logging.info(logged_to_csv.format(file.name))
|
||||||
if prompt == 'y':
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
with open(f"output/{repo_name}_release_{release['name']}.csv", 'w') as file:
|
|
||||||
writecsv = csv.writer(file)
|
|
||||||
writecsv.writerow(repo_release_fields)
|
# create .csv for repository releases
|
||||||
writecsv.writerow(repo_release_row)
|
def log_repo_releases(release, repo_name):
|
||||||
|
repo_release_fields = ['Name', 'ID', 'Node ID', 'Tag', 'Branch', 'Assets', 'Is draft?', 'Is prerelease?',
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
'Created at', 'Published at']
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
repo_release_row = [release['name'], release['id'], release['node_id'], release['tag_name'],
|
||||||
|
release['target_commitish'], release['assets'], release['draft'], release['prerelease'],
|
||||||
else:
|
release['created_at'], release['published_at']]
|
||||||
logging.info(logRoller.loggingSkipped)
|
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
with open(os.path.join("output", f"{repo_name}_release_{release['name']}.csv"), 'w') as file:
|
||||||
|
write_csv = csv.writer(file)
|
||||||
|
write_csv.writerow(repo_release_fields)
|
||||||
# Create .csv file for repository contributors
|
write_csv.writerow(repo_release_row)
|
||||||
def logRepoContributors(contributor, repo_name):
|
|
||||||
repo_contributor_fields = ['Profile photo', 'Username', 'ID', 'Node ID', 'Gravatar ID', 'Account type', 'Is site admin?', 'URL']
|
logging.info(logged_to_csv.format(file.name))
|
||||||
repo_contributor_row = [contributor['avatar_url'], contributor['login'], contributor['id'], contributor['node_id'], contributor['gravatar_id'], contributor['type'], contributor['site_admin'], contributor['html_url']]
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
|
||||||
if prompt == 'y':
|
|
||||||
with open(f"output/{contributor['login']}_contributor_of_{repo_name}.csv", 'w') as file:
|
# Create .csv file for repository contributors
|
||||||
writecsv = csv.writer(file)
|
def log_repo_contributors(contributor, repo_name):
|
||||||
writecsv.writerow(repo_contributor_fields)
|
repo_contributor_fields = ['Profile photo', 'Username', 'ID', 'Node ID', 'Gravatar ID', 'Account type',
|
||||||
writecsv.writerow(repo_contributor_row)
|
'Is site admin?', 'URL']
|
||||||
|
repo_contributor_row = [contributor['avatar_url'], contributor['login'], contributor['id'], contributor['node_id'],
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
contributor['gravatar_id'], contributor['type'], contributor['site_admin'],
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
contributor['html_url']]
|
||||||
|
|
||||||
else:
|
with open(os.path.join("output", f"{contributor['login']}_contributor_of_{repo_name}.csv"), 'w') as file:
|
||||||
logging.info(logRoller.loggingSkipped)
|
write_csv = csv.writer(file)
|
||||||
print(f"{SignVar.info} {logRoller.loggingSkipped}\n")
|
write_csv.writerow(repo_contributor_fields)
|
||||||
|
write_csv.writerow(repo_contributor_row)
|
||||||
|
|
||||||
# Create .csv for organization' events
|
logging.info(logged_to_csv.format(file.name))
|
||||||
def logOrgEvents(event, organization):
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
org_event_fields = ['ID', 'Type', 'Created at', 'Payload']
|
|
||||||
org_event_row = [event['id'], event['type'], event['created_at'], event['payload']]
|
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
# Create .csv for organization' events
|
||||||
if prompt == 'y':
|
def log_repo_events(event, organization):
|
||||||
with open(f"output/{organization}_event_{event['id']}.csv", 'w') as file:
|
org_event_fields = ['ID', 'Type', 'Created at', 'Payload']
|
||||||
writecsv = csv.writer(file)
|
org_event_row = [event['id'], event['type'], event['created_at'], event['payload']]
|
||||||
writecsv.writerow(org_event_fields)
|
|
||||||
writecsv.writerow(org_event_row)
|
with open(os.path.join("output", f"{organization}_event_{event['id']}.csv"), 'w') as file:
|
||||||
|
write_csv = csv.writer(file)
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
write_csv.writerow(org_event_fields)
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
write_csv.writerow(org_event_row)
|
||||||
|
|
||||||
else:
|
logging.info(logged_to_csv.format(file.name))
|
||||||
logging.info(logRoller.loggingSkipped)
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
|
||||||
|
|
||||||
|
# Create .csv for organization' repositories
|
||||||
# Create .csv for organization' repositories
|
def log_org_repos(repository, organization):
|
||||||
def logOrgRepos(repository, organization):
|
org_repo_fields = ['Name', 'ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility',
|
||||||
org_repo_fields = [ 'Name','ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility', 'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?', 'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?', 'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?',
|
||||||
org_repo_row = [repository['full_name'], repository['id'], repository['description'], repository['forks'], repository['stargazers_count'], repository['watchers'], repository['license'], repository['default_branch'], repository['visibility'], repository['language'], repository['open_issues'], repository['topics'], repository['homepage'], repository['clone_url'], repository['ssh_url'], repository['fork'], repository['allow_forking'], repository['private'], repository['archived'], repository['is_template'], repository['has_wiki'], repository['has_pages'], repository['has_projects'], repository['has_issues'], repository['has_downloads'], repository['pushed_at'], repository['created_at'], repository['updated_at']]
|
'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?',
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
||||||
if prompt == 'y':
|
org_repo_row = [repository['full_name'], repository['id'], repository['description'], repository['forks'],
|
||||||
with open(f"output/{repository['name']}_repository_of_{organization}.csv", 'w') as file:
|
repository['stargazers_count'], repository['watchers'], repository['license'],
|
||||||
writecsv = csv.writer(file)
|
repository['default_branch'], repository['visibility'], repository['language'],
|
||||||
writecsv.writerow(org_repo_fields)
|
repository['open_issues'], repository['topics'], repository['homepage'], repository['clone_url'],
|
||||||
writecsv.writerow(org_repo_row)
|
repository['ssh_url'], repository['fork'], repository['allow_forking'], repository['private'],
|
||||||
|
repository['archived'], repository['is_template'], repository['has_wiki'], repository['has_pages'],
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
repository['has_projects'], repository['has_issues'], repository['has_downloads'],
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
repository['pushed_at'], repository['created_at'], repository['updated_at']]
|
||||||
|
|
||||||
else:
|
with open(os.path.join("output", f"{repository['name']}_repository_of_{organization}.csv"), 'w') as file:
|
||||||
logging.info(logRoller.loggingSkipped)
|
write_csv = csv.writer(file)
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
write_csv.writerow(org_repo_fields)
|
||||||
|
write_csv.writerow(org_repo_row)
|
||||||
|
|
||||||
# .csv for user' repositories
|
logging.info(logged_to_csv.format(file.name))
|
||||||
def logUserRepos(repository, username):
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
user_repo_fields = [ 'Name','ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility', 'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?', 'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?', 'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
|
||||||
user_repo_row = [repository['full_name'], repository['id'], repository['description'], repository['forks'], repository['stargazers_count'], repository['watchers'], repository['license'], repository['default_branch'], repository['visibility'], repository['language'], repository['open_issues'], repository['topics'], repository['homepage'], repository['clone_url'], repository['ssh_url'], repository['fork'], repository['allow_forking'], repository['private'], repository['archived'], repository['is_template'], repository['has_wiki'], repository['has_pages'], repository['has_projects'], repository['has_issues'], repository['has_downloads'], repository['pushed_at'], repository['created_at'], repository['updated_at']]
|
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
# .csv for user' repositories
|
||||||
if prompt == 'y':
|
def log_user_repos(repository, username):
|
||||||
with open(f"output/{repository['name']}_{username}.csv", 'w') as file:
|
user_repo_fields = ['Name', 'ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility',
|
||||||
writecsv = csv.writer(file)
|
'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?',
|
||||||
writecsv.writerow(user_repo_fields)
|
'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?',
|
||||||
writecsv.writerow(user_repo_row)
|
'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
||||||
|
user_repo_row = [repository['full_name'], repository['id'], repository['description'], repository['forks'],
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
repository['stargazers_count'], repository['watchers'], repository['license'],
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
repository['default_branch'], repository['visibility'], repository['language'],
|
||||||
|
repository['open_issues'], repository['topics'], repository['homepage'], repository['clone_url'],
|
||||||
else:
|
repository['ssh_url'], repository['fork'], repository['allow_forking'], repository['private'],
|
||||||
logging.info(logRoller.loggingSkipped)
|
repository['archived'], repository['is_template'], repository['has_wiki'], repository['has_pages'],
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
repository['has_projects'], repository['has_issues'], repository['has_downloads'],
|
||||||
|
repository['pushed_at'], repository['created_at'], repository['updated_at']]
|
||||||
|
|
||||||
# .csv for user events
|
with open(os.path.join("output", f"{repository['name']}_{username}.csv"), 'w') as file:
|
||||||
def logUserEvents(event):
|
write_csv = csv.writer(file)
|
||||||
user_event_fields = ['Actor', 'Type', 'Repository', 'Created at', 'Payload']
|
write_csv.writerow(user_repo_fields)
|
||||||
user_event_row = [event['actor']['login'], event['type'], event['repo']['name'], event['created_at'], event['payload']]
|
write_csv.writerow(user_repo_row)
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
|
||||||
if prompt == 'y':
|
logging.info(logged_to_csv.format(file.name))
|
||||||
with open(f"output/{event['actor']['login']}_event_{event['id']}.csv", 'w') as file:
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
writecsv = csv.writer(file)
|
|
||||||
writecsv.writerow(user_event_fields)
|
|
||||||
writecsv.writerow(user_event_row)
|
# .csv for user events
|
||||||
|
def log_user_events(event):
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
user_event_fields = ['Actor', 'Type', 'Repository', 'Created at', 'Payload']
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
user_event_row = [event['actor']['login'], event['type'], event['repo']['name'], event['created_at'],
|
||||||
|
event['payload']]
|
||||||
else:
|
|
||||||
logging.info(logRoller.loggingSkipped)
|
with open(os.path.join("output", f"{event['actor']['login']}_event_{event['id']}.csv"), 'w') as file:
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
write_csv = csv.writer(file)
|
||||||
|
write_csv.writerow(user_event_fields)
|
||||||
|
write_csv.writerow(user_event_row)
|
||||||
# .csv for user gists
|
|
||||||
def logUserGists(gist):
|
logging.info(logged_to_csv.format(file.name))
|
||||||
user_gist_fields = ['ID', 'Node ID', 'About', 'Comments', 'Files', 'Git Push URL', 'Is public?', 'Is truncated?', 'Updated at']
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
user_gist_row = [gist['id'], gist['node_id'], gist['description'], gist['comments'], gist['files'], gist['git_push_url'], gist['public'], gist['truncated'], gist['updated_at']]
|
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
|
||||||
if prompt == 'y':
|
# .csv for user gists
|
||||||
with open(f"output/{gist['id']}_gists_{gist['owner']['login']}.csv", 'w') as file:
|
def log_user_gists(gist):
|
||||||
writecsv = csv.writer(file)
|
user_gist_fields = ['ID', 'Node ID', 'About', 'Comments', 'Files', 'Git Push URL', 'Is public?', 'Is truncated?',
|
||||||
writecsv.writerow(user_gist_fields)
|
'Updated at']
|
||||||
writecsv.writerow(user_gist_row)
|
user_gist_row = [gist['id'], gist['node_id'], gist['description'], gist['comments'], gist['files'],
|
||||||
|
gist['git_push_url'], gist['public'], gist['truncated'], gist['updated_at']]
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
with open(os.path.join("output", f"{gist['id']}_gists_{gist['owner']['login']}.csv"), 'w') as file:
|
||||||
|
write_csv = csv.writer(file)
|
||||||
else:
|
write_csv.writerow(user_gist_fields)
|
||||||
logging.info(logRoller.loggingSkipped)
|
write_csv.writerow(user_gist_row)
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
|
||||||
|
logging.info(logged_to_csv.format(file.name))
|
||||||
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
# .csv for user followers
|
|
||||||
def logUserFollowers(follower, username):
|
|
||||||
user_follower_fields = ['Profile photo', 'Username', 'ID', 'Node ID', 'Gravatar ID', 'Account type', 'Is site admin?', 'URL']
|
# .csv for user followers
|
||||||
user_follower_row = [follower['avatar_url'], follower['login'], follower['id'], follower['node_id'], follower['gravatar_id'], follower['type'], follower['site_admin'], follower['html_url']]
|
def log_user_followers(follower, username):
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
user_follower_fields = ['Profile photo', 'Username', 'ID', 'Node ID', 'Gravatar ID', 'Account type',
|
||||||
if prompt == 'y':
|
'Is site admin?', 'URL']
|
||||||
with open(f"output/{follower['login']}_follower_of_{username}.csv", 'w') as file:
|
user_follower_row = [follower['avatar_url'], follower['login'], follower['id'], follower['node_id'],
|
||||||
writecsv = csv.writer(file)
|
follower['gravatar_id'], follower['type'], follower['site_admin'], follower['html_url']]
|
||||||
writecsv.writerow(user_follower_fields)
|
|
||||||
writecsv.writerow(user_follower_row)
|
with open(f"output/{follower['login']}_follower_of_{username}.csv", 'w') as file:
|
||||||
|
write_csv = csv.writer(file)
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
write_csv.writerow(user_follower_fields)
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
write_csv.writerow(user_follower_row)
|
||||||
|
|
||||||
else:
|
logging.info(logged_to_csv.format(file.name))
|
||||||
logging.info(logRoller.loggingSkipped)
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
|
||||||
|
|
||||||
|
# .csv for user following
|
||||||
# .csv for user following
|
def log_user_following(user, username):
|
||||||
def logUserFollowing(user, username):
|
user_following_fields = ['Profile photo', 'Username', 'ID', 'Node ID', 'Gravatar ID', 'Account type',
|
||||||
user_following_fields = ['Profile photo', 'Username', 'ID', 'Node ID', 'Gravatar ID', 'Account type', 'Is site admin?', 'URL']
|
'Is site admin?', 'URL']
|
||||||
user_following_row = [user['avatar_url'], user['login'], user['id'], user['node_id'], user['gravatar_id'], user['type'], user['site_admin'], user['html_url']]
|
user_following_row = [user['avatar_url'], user['login'], user['id'], user['node_id'], user['gravatar_id'],
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
user['type'], user['site_admin'], user['html_url']]
|
||||||
if prompt == 'y':
|
|
||||||
with open(f"output/{user['login']}_followed_by_{username}.csv", 'w') as file:
|
with open(os.path.join("output", f"{user['login']}_followed_by_{username}.csv"), 'w') as file:
|
||||||
writecsv = csv.writer(file)
|
write_csv = csv.writer(file)
|
||||||
writecsv.writerow(user_following_fields)
|
write_csv.writerow(user_following_fields)
|
||||||
writecsv.writerow(user_following_row)
|
write_csv.writerow(user_following_row)
|
||||||
|
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
logging.info(logged_to_csv.format(file.name))
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
|
|
||||||
else:
|
|
||||||
logging.info(logRoller.loggingSkipped)
|
# .csv for user' subscriptions
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
def log_user_subscriptions(repository, username):
|
||||||
|
user_subscription_fields = ['Name', 'ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility',
|
||||||
|
'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?',
|
||||||
# .csv for user' subscriptions
|
'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?',
|
||||||
def logUserSubscriptions(repository, username):
|
'Has pages?', 'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at',
|
||||||
user_subscription_fields = [ 'Name','ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility', 'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?', 'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?', 'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
'Created at', 'Updated at']
|
||||||
user_subscription_row = [repository['name'], repository['id'], repository['description'], repository['forks'], repository['stargazers_count'], repository['watchers'], repository['license'], repository['default_branch'], repository['visibility'], repository['language'], repository['open_issues'], repository['topics'], repository['homepage'], repository['clone_url'], repository['ssh_url'], repository['fork'], repository['allow_forking'], repository['private'], repository['archived'], repository['is_template'], repository['has_wiki'], repository['has_pages'], repository['has_projects'], repository['has_issues'], repository['has_downloads'], repository['pushed_at'], repository['created_at'], repository['updated_at']]
|
user_subscription_row = [repository['name'], repository['id'], repository['description'], repository['forks'],
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
repository['stargazers_count'], repository['watchers'], repository['license'],
|
||||||
if prompt == 'y':
|
repository['default_branch'], repository['visibility'], repository['language'],
|
||||||
with open(f"output/{username}_subscriptions_{repository['name']}.csv", 'w') as file:
|
repository['open_issues'], repository['topics'], repository['homepage'],
|
||||||
writecsv = csv.writer(file)
|
repository['clone_url'], repository['ssh_url'], repository['fork'],
|
||||||
writecsv.writerow(user_subscription_fields)
|
repository['allow_forking'], repository['private'], repository['archived'],
|
||||||
writecsv.writerow(user_subscription_row)
|
repository['is_template'], repository['has_wiki'], repository['has_pages'],
|
||||||
|
repository['has_projects'], repository['has_issues'], repository['has_downloads'],
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
repository['pushed_at'], repository['created_at'], repository['updated_at']]
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
|
||||||
|
with open(os.path.join("output", f"{username}_subscriptions_{repository['name']}.csv"), 'w') as file:
|
||||||
else:
|
write_csv = csv.writer(file)
|
||||||
logging.info(logRoller.loggingSkipped)
|
write_csv.writerow(user_subscription_fields)
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
write_csv.writerow(user_subscription_row)
|
||||||
|
|
||||||
|
logging.info(logged_to_csv.format(file.name))
|
||||||
# .csv for user organizations
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
def logUserOrgs(organization, username):
|
|
||||||
user_org_fields = ['Profile photo', 'Name', 'ID', 'Node ID', 'URL', 'About']
|
|
||||||
user_org_row = [organization['avatar_url'], organization['login'], organization['id'], organization['node_id'], organization['url'], organization['description']]
|
# .csv for user organizations
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
def log_user_orgs(organization, username):
|
||||||
if prompt == 'y':
|
user_org_fields = ['Profile photo', 'Name', 'ID', 'Node ID', 'URL', 'About']
|
||||||
with open(f"output/{organization['login']}_{username}.csv", 'w') as file:
|
user_org_row = [organization['avatar_url'], organization['login'], organization['id'], organization['node_id'],
|
||||||
writecsv = csv.writer(file)
|
organization['url'], organization['description']]
|
||||||
writecsv.writerow(user_org_fields)
|
|
||||||
writecsv.writerow(user_org_row)
|
with open(os.path.join("output", f"{organization['login']}_{username}.csv"), 'w') as file:
|
||||||
|
write_csv = csv.writer(file)
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
write_csv.writerow(user_org_fields)
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
write_csv.writerow(user_org_row)
|
||||||
|
|
||||||
else:
|
logging.info(logged_to_csv.format(file.name))
|
||||||
logging.info(logRoller.loggingSkipped)
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
|
||||||
|
|
||||||
|
# Create .csv for user search
|
||||||
# Create .csv for user search
|
def log_users_search(user, query):
|
||||||
def logUserSearch(user, query):
|
user_search_fields = ['Profile photo', 'Username', 'ID', 'Node ID', 'Gravatar ID', 'Account type', 'Is site admin?',
|
||||||
user_search_fields = ['Profile photo', 'Username', 'ID', 'Node ID', 'Gravatar ID', 'Account type', 'Is site admin?', 'URL']
|
'URL']
|
||||||
user_search_row = [user['avatar_url'], user['login'], user['id'], user['node_id'], user['gravatar_id'], user['type'], user['site_admin'], user['html_url']]
|
user_search_row = [user['avatar_url'], user['login'], user['id'], user['node_id'], user['gravatar_id'],
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
user['type'], user['site_admin'], user['html_url']]
|
||||||
if prompt == 'y':
|
|
||||||
with open(f"output/{user['login']}_user_search_result_for_{query}.csv", 'w') as file:
|
with open(os.path.join("output", f"{user['login']}_user_search_result_for_{query}.csv"), 'w') as file:
|
||||||
writecsv = csv.writer(file)
|
write_csv = csv.writer(file)
|
||||||
writecsv.writerow(user_search_fields)
|
write_csv.writerow(user_search_fields)
|
||||||
writecsv.writerow(user_search_row)
|
write_csv.writerow(user_search_row)
|
||||||
|
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
logging.info(logged_to_csv.format(file.name))
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
|
|
||||||
else:
|
|
||||||
logging.info(logRoller.loggingSkipped)
|
# Create .csv for repository search
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
def log_repos_search(repository, query):
|
||||||
|
repo_search_fields = ['Name', 'ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility',
|
||||||
|
'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?',
|
||||||
# Create .csv for repository search
|
'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?',
|
||||||
def logRepoSearch(repository, query):
|
'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
||||||
repo_search_fields = [ 'Name','ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility', 'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?', 'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?', 'Has projects?', 'Has issues?', 'Has downloads?', 'Pushed at', 'Created at', 'Updated at']
|
repo_search_row = [repository['full_name'], repository['id'], repository['description'], repository['forks'],
|
||||||
repo_search_row = [repository['full_name'], repository['id'], repository['description'], repository['forks'], repository['stargazers_count'], repository['watchers'], repository['license'], repository['default_branch'], repository['visibility'], repository['language'], repository['open_issues'], repository['topics'], repository['homepage'], repository['clone_url'], repository['ssh_url'], repository['fork'], repository['allow_forking'], repository['private'], repository['archived'], repository['is_template'], repository['has_wiki'], repository['has_pages'], repository['has_projects'], repository['has_issues'], repository['has_downloads'], repository['pushed_at'], repository['created_at'], repository['updated_at']]
|
repository['stargazers_count'], repository['watchers'], repository['license'],
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
repository['default_branch'], repository['visibility'], repository['language'],
|
||||||
if prompt == 'y':
|
repository['open_issues'], repository['topics'], repository['homepage'], repository['clone_url'],
|
||||||
with open(f"output/{repository['name']}_repository_search_result_for_{query}.csv", 'w') as file:
|
repository['ssh_url'], repository['fork'], repository['allow_forking'], repository['private'],
|
||||||
writecsv = csv.writer(file)
|
repository['archived'], repository['is_template'], repository['has_wiki'],
|
||||||
writecsv.writerow(repo_search_fields)
|
repository['has_pages'], repository['has_projects'], repository['has_issues'],
|
||||||
writecsv.writerow(repo_search_row)
|
repository['has_downloads'], repository['pushed_at'], repository['created_at'],
|
||||||
|
repository['updated_at']]
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
with open(os.path.join("output", f"{repository['name']}_repository_search_result_for_{query}.csv"), 'w') as file:
|
||||||
|
write_csv = csv.writer(file)
|
||||||
else:
|
write_csv.writerow(repo_search_fields)
|
||||||
logging.info(logRoller.loggingSkipped)
|
write_csv.writerow(repo_search_row)
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
|
||||||
|
logging.info(logged_to_csv.format(file.name))
|
||||||
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
# Create .csv for topic search
|
|
||||||
def logTopicSearch(topic, query):
|
|
||||||
topic_search_fields = ['Name', 'Score', 'Curated', 'Featured', 'Display name', 'Created by', 'Created at', 'Updated at']
|
# Create .csv for topic search
|
||||||
topic_search_row = [topic['name'], topic['score'], topic['curated'], topic['featured'], topic['display_name'], topic['created_by'], topic['created_at'], topic['updated_at']]
|
def log_topics_search(topic, query):
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
topic_search_fields = ['Name', 'Score', 'Curated', 'Featured', 'Display name', 'Created by', 'Created at',
|
||||||
if prompt == 'y':
|
'Updated at']
|
||||||
with open(f"output/{topic['name']}_topic_search_result_for_{query}.csv", 'w') as file:
|
topic_search_row = [topic['name'], topic['score'], topic['curated'], topic['featured'], topic['display_name'],
|
||||||
writecsv = csv.writer(file)
|
topic['created_by'], topic['created_at'], topic['updated_at']]
|
||||||
writecsv.writerow(topic_search_fields)
|
|
||||||
writecsv.writerow(topic_search_row)
|
with open(os.path.join("output", f"{topic['name']}_topic_search_result_for_{query}.csv"), 'w') as file:
|
||||||
|
write_csv = csv.writer(file)
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
write_csv.writerow(topic_search_fields)
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
write_csv.writerow(topic_search_row)
|
||||||
|
|
||||||
else:
|
logging.info(logged_to_csv.format(file.name))
|
||||||
logging.info(logRoller.loggingSkipped)
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
|
||||||
|
|
||||||
|
# Create .csv for issues search
|
||||||
# Create .csv for issues search
|
def log_issues_search(issue, query):
|
||||||
def logIssueSearch(issue, query):
|
issue_search_fields = ['Title', 'ID', 'Node ID', 'Number', 'State', 'Reactions', 'Comments', 'Milestone',
|
||||||
issue_search_fields = ['Title', 'ID', 'Node ID', 'Number', 'State', 'Reactions', 'Comments', 'Milestone', 'Assignee', 'Assignees', 'Author association', 'Labels', 'Is locked?', 'Lock reason', 'Closed at', 'Created at', 'Updated at']
|
'Assignee', 'Assignees', 'Author association', 'Labels', 'Is locked?', 'Lock reason',
|
||||||
issue_search_row = [issue['title'], issue['id'], issue['node_id'], issue['number'], issue['state'], issue['reactions'], issue['comments'], issue['milestone'], issue['assignee'], issue['assignees'], issue['author_association'], issue['labels'], issue['locked'], issue['active_lock_reason'], issue['closed_at'], issue['created_at'], issue['updated_at']]
|
'Closed at', 'Created at', 'Updated at']
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
issue_search_row = [issue['title'], issue['id'], issue['node_id'], issue['number'], issue['state'],
|
||||||
if prompt == 'y':
|
issue['reactions'], issue['comments'], issue['milestone'], issue['assignee'],
|
||||||
with open(f"output/{issue['id']}_issue_search_result_for_{query}.csv", 'w') as file:
|
issue['assignees'], issue['author_association'], issue['labels'], issue['locked'],
|
||||||
writecsv = csv.writer(file)
|
issue['active_lock_reason'], issue['closed_at'], issue['created_at'], issue['updated_at']]
|
||||||
writecsv.writerow(issue_search_fields)
|
|
||||||
writecsv.writerow(issue_search_row)
|
with open(os.path.join("output", f"{issue['id']}_issue_search_result_for_{query}.csv"), 'w') as file:
|
||||||
|
write_csv = csv.writer(file)
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
write_csv.writerow(issue_search_fields)
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
write_csv.writerow(issue_search_row)
|
||||||
|
|
||||||
else:
|
logging.info(logged_to_csv.format(file.name))
|
||||||
logging.info(logRoller.loggingSkipped)
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
|
||||||
|
|
||||||
|
# Create .csv for commits search
|
||||||
# Create .csv for commits search
|
def log_commits_search(commit, query):
|
||||||
def logCommitsSearch(commit, query):
|
commit_search_fields = ['SHA', 'Author', 'Username', 'Email', 'Committer', 'Repository', 'URL', 'Description']
|
||||||
commit_search_fields = ['SHA', 'Author', 'Username', 'Email', 'Committer', 'Repository', 'URL', 'Description']
|
commit_search_row = [commit['commit']['tree']['sha'], commit['commit']['author']['name'], commit['author']['login'],
|
||||||
commit_search_row = [commit['commit']['tree']['sha'], commit['commit']['author']['name'], commit['author']['login'], commit['commit']['author']['email'], commit['commit']['committer']['name'], commit['repository']['full_name'], commit['html_url'], commit['commit']['message']]
|
commit['commit']['author']['email'], commit['commit']['committer']['name'],
|
||||||
prompt = input(f'\n{SignVar.prompt} {logRoller.askLogCsv}').lower()
|
commit['repository']['full_name'], commit['html_url'], commit['commit']['message']]
|
||||||
if prompt == 'y':
|
|
||||||
with open(f"output/{commit['commit']['tree']['sha']}_commit_search_result_for_{query}.csv", 'w') as file:
|
with open(os.path.join("output", f"{commit['commit']['tree']['sha']}_commit_search_result_for_{query}.csv"), 'w') as file:
|
||||||
writecsv = csv.writer(file)
|
write_csv = csv.writer(file)
|
||||||
writecsv.writerow(commit_search_fields)
|
write_csv.writerow(commit_search_fields)
|
||||||
writecsv.writerow(commit_search_row)
|
write_csv.writerow(commit_search_row)
|
||||||
|
|
||||||
logging.info(logRoller.loggedToCsv.format(file.name))
|
logging.info(logged_to_csv.format(file.name))
|
||||||
sys.stdout.write(f"{SignVar.positive} {logRoller.loggedToCsv.format(file.name)}\n")
|
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
|
||||||
|
|
||||||
else:
|
|
||||||
logging.info(logRoller.loggingSkipped)
|
|
||||||
sys.stdout.write(f"{SignVar.info} ({prompt}) {logRoller.loggingSkipped}\n")
|
|
||||||
|
|||||||
@@ -1,231 +1,170 @@
|
|||||||
import sys
|
from rich.table import Table
|
||||||
from octosuite.colors import Color
|
from octosuite.config import Tree, xprint, white, green, white_bold, green_bold, header_title, reset
|
||||||
|
|
||||||
"""
|
# helper.py
|
||||||
Help
|
# This file holds the help text for available commands.
|
||||||
This class holds the help text for available.
|
usage_text = 'Use syntax {} to get started with %s{}%s.' % (green_bold, reset)
|
||||||
Almost everything in the methods from this class is hard coded
|
usage_text_1 = '%sUse {} to view all available subcommands.%s' % (white, reset)
|
||||||
"""
|
usage_text_2 = "%sThe {} command works with subcommands. %s" % (white, reset)
|
||||||
class Help:
|
|
||||||
usageText = 'Use {} to get started'
|
|
||||||
usageText1 = 'Use {} to view all available subcommands.'
|
|
||||||
|
|
||||||
def Org():
|
|
||||||
sys.stdout.write(f"""
|
|
||||||
{Color.white}Note:
|
|
||||||
-------
|
|
||||||
The '{Color.green}org{Color.white}' command works with subcommands.
|
|
||||||
{Help.usageText1.format('help:org')}{Color.reset}
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def Repo():
|
def org():
|
||||||
sys.stdout.write(f"""
|
xprint(usage_text_2.format(f"{green_bold}org{reset}") + usage_text_1.format(f"{green_bold}help:org{reset}"))
|
||||||
{Color.white}Note:
|
|
||||||
-----
|
|
||||||
The '{Color.green}repo{Color.white}' command works with subcommands.
|
|
||||||
{Help.usageText1.format('help:repo')}{Color.reset}
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def User():
|
def repo():
|
||||||
sys.stdout.write(f"""
|
xprint(usage_text_2.format(f"{green_bold}repo{reset}") + usage_text_1.format(f"{green_bold}help:repo{reset}"))
|
||||||
{Color.white}Note:
|
|
||||||
-----
|
|
||||||
The '{Color.green}user{Color.white}' command works with subcommands.
|
|
||||||
{Help.usageText1.format('help:user')}{Color.reset}
|
|
||||||
""")
|
|
||||||
|
|
||||||
def Search():
|
|
||||||
sys.stdout.write(f"""
|
|
||||||
{Color.white}Note:
|
|
||||||
-----
|
|
||||||
The '{Color.green}search{Color.white}' command works with subcommands.
|
|
||||||
{Help.usageText1.format('help:search')}{Color.reset}
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def Source():
|
def user():
|
||||||
sys.stdout.write(f"""
|
xprint(usage_text_2.format(f"{green_bold}user{reset}") + usage_text_1.format(f"{green_bold}help:user{reset}"))
|
||||||
{Color.white}Note:
|
|
||||||
-----
|
|
||||||
The '{Color.green}source{Color.white}' command works with subcommands.
|
|
||||||
{Help.usageText1.format('help:source')}{Color.reset}
|
|
||||||
""")
|
|
||||||
|
|
||||||
def Logs():
|
|
||||||
sys.stdout.write(f"""
|
|
||||||
{Color.white}Note:
|
|
||||||
-----
|
|
||||||
The '{Color.green}logs{Color.white}' command works with subcommands.
|
|
||||||
{Help.usageText1.format('help:logs')}{Color.reset}
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def Version():
|
def search():
|
||||||
sys.stdout.write(f"""
|
xprint(usage_text_2.format(f"{green_bold}search{reset}") + usage_text_1.format(f"{green_bold}help:search{reset}"))
|
||||||
{Color.white}Note:
|
|
||||||
-----
|
|
||||||
The '{Color.green}version{Color.white}' command works with subcommands.
|
|
||||||
{Help.usageText1.format('help:version')}{Color.reset}
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def Csv():
|
def source():
|
||||||
sys.stdout.write(f"""
|
xprint(usage_text_2.format(f"{green_bold}source{reset}") + usage_text_1.format(f"{green_bold}help:source{reset}"))
|
||||||
{Color.white}Note:
|
|
||||||
-----
|
|
||||||
The '{Color.green}csv{Color.white}' command works with subcommands.
|
|
||||||
{Help.usageText1.format('help:csv')}{Color.reset}
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def versionCommand():
|
def logs():
|
||||||
sys.stdout.write(f"""
|
xprint(usage_text_2.format(f"{green_bold}logs{reset}") + usage_text_1.format(f"{green_bold}help:logs{reset}"))
|
||||||
{Color.white}Version subcommands{Color.reset}
|
|
||||||
{'='*18}
|
|
||||||
{Help.usageText.format('version:<subcommand>')}
|
|
||||||
|
|
||||||
{Color.white}Command Description{Color.reset}
|
|
||||||
------- -----------
|
|
||||||
check Check for new release(s)
|
|
||||||
info Version info
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def sourceCommand():
|
def csv():
|
||||||
sys.stdout.write(f"""
|
xprint(usage_text_2.format(f"{green_bold}csv{reset}") + usage_text_1.format(f"{green_bold}help:csv{reset}"))
|
||||||
{Color.white}Source subcommands{Color.reset}
|
|
||||||
{'='*18}
|
|
||||||
{Help.usageText.format('source:<subcommand>')}
|
|
||||||
{Color.white}Command Description{Color.reset}
|
|
||||||
-------- -----------
|
|
||||||
zipball Download source code as zipball
|
|
||||||
tarball Download source code as tarball
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def searchCommand():
|
def source_command():
|
||||||
sys.stdout.write(f"""
|
source_cmd_table = Table(show_header=True, header_style=header_title)
|
||||||
{Color.white}Search subcommands{Color.reset}
|
source_cmd_table.add_column("Command", style="dim")
|
||||||
{'='*18}
|
source_cmd_table.add_column("Description")
|
||||||
{Help.usageText.format('search:<subcommand>')}
|
source_cmd_table.add_row("zipball", "Download source code Zipball")
|
||||||
|
source_cmd_table.add_row("tarball", "Download source code Tarball")
|
||||||
|
|
||||||
{Color.white}Command Description{Color.reset}
|
syntax = f"{green}source:<command>{reset}"
|
||||||
------- -----------
|
xprint(f"{usage_text.format(syntax, 'source code downloads')}")
|
||||||
users Search user(s)
|
xprint(source_cmd_table)
|
||||||
repos Search repositor[yies]
|
|
||||||
topics Search topic(s)
|
|
||||||
issues Search issue(s)
|
|
||||||
commits Search commit(s)
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def userCommand():
|
def search_command():
|
||||||
sys.stdout.write(f"""
|
search_cmd_table = Table(show_header=True, header_style=header_title)
|
||||||
{Color.white}User subcommands{Color.reset}
|
search_cmd_table.add_column("Command", style="dim")
|
||||||
{'='*17}
|
search_cmd_table.add_column("Description")
|
||||||
{Help.usageText.format('user:<subcommand>')}
|
search_cmd_table.add_row("users", "Search user(s)")
|
||||||
|
search_cmd_table.add_row("repos", "Search repositor[y][ies]")
|
||||||
|
search_cmd_table.add_row("topics", "Search topic(s)")
|
||||||
|
search_cmd_table.add_row("issues", "Search issue(s)")
|
||||||
|
search_cmd_table.add_row("commits", "Search commit(s)")
|
||||||
|
|
||||||
{Color.white}Command Description{Color.reset}
|
syntax = f"{green}search:<command>{reset}"
|
||||||
------- -----------
|
xprint(f"{usage_text.format(syntax, 'target discovery')}")
|
||||||
profile Get a user's profile info
|
xprint(search_cmd_table)
|
||||||
gists Return a users's gists
|
|
||||||
orgs Return organizations that a user belongs to/owns
|
|
||||||
repos Return a user's repositories
|
|
||||||
events Return a user's events
|
|
||||||
follows Check if user(A) follows user(B)
|
|
||||||
followers Return a user's followers
|
|
||||||
following Return a list of users the target is following
|
|
||||||
subscriptions Return a user's subscriptions
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def orgCommand():
|
def user_command():
|
||||||
sys.stdout.write(f"""
|
user_cmd_table = Table(show_header=True, header_style=header_title)
|
||||||
{Color.white}Org subcommands{Color.reset}
|
user_cmd_table.add_column("Command", style="dim")
|
||||||
{'='*16}
|
user_cmd_table.add_column("Description")
|
||||||
{Help.usageText.format('org:<subcommand>')}
|
user_cmd_table.add_row("profile", "Get a target's profile info")
|
||||||
|
user_cmd_table.add_row("gists", "Return a users's gists")
|
||||||
|
user_cmd_table.add_row("org", "Return organizations that a target belongs to/owns")
|
||||||
|
user_cmd_table.add_row("repos", "Return a target's repositories")
|
||||||
|
user_cmd_table.add_row("events", "Return a target's events")
|
||||||
|
user_cmd_table.add_row("follows", "Check if user(A) follows user(B)")
|
||||||
|
user_cmd_table.add_row("followers", "Return a target's followers")
|
||||||
|
user_cmd_table.add_row("following", "Return a list of users the target is following")
|
||||||
|
user_cmd_table.add_row("subscriptions", "Return a target's subscriptions")
|
||||||
|
|
||||||
{Color.white}Command Description{Color.reset}
|
syntax = f"{green}user:<command>{reset}"
|
||||||
------- -----------
|
xprint(f"{usage_text.format(syntax, 'user investigation(s)')}")
|
||||||
profile Get an organization's info
|
xprint(user_cmd_table)
|
||||||
repos Return an organization's repositories
|
|
||||||
events Return an organization's events
|
|
||||||
member Check if a specified user is a public member of the target organization
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def repoCommand():
|
def org_command():
|
||||||
sys.stdout.write(f"""
|
org_cmd_table = Table(show_header=True, header_style=header_title)
|
||||||
{Color.white}Repo subcommands{Color.reset}
|
org_cmd_table.add_column("Command", style="dim")
|
||||||
{'='*17}
|
org_cmd_table.add_column("Description")
|
||||||
{Help.usageText.format('repo:<subcommand>')}
|
org_cmd_table.add_row("profile", "Get a target organization' profile info")
|
||||||
|
org_cmd_table.add_row("repos", "Return a target organization' repositories")
|
||||||
|
org_cmd_table.add_row("events", "Return a target organization' events")
|
||||||
|
org_cmd_table.add_row("member", "Check if a specified user is a public member of the target organization")
|
||||||
|
|
||||||
{Color.white}Command Description{Color.reset}
|
syntax = f"{green}org:<command>{reset}"
|
||||||
------- -----------
|
xprint(f"{usage_text.format(syntax, 'organization investigation(s)')}")
|
||||||
profile Get a repository's info
|
xprint(org_cmd_table)
|
||||||
issues Return a repository's issues
|
|
||||||
forks Return a repository's forks
|
|
||||||
releases Return a repository's releases
|
|
||||||
stargazers Return a repository's stargazers
|
|
||||||
pathcontents List contents in a path of a repository
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def logsCommand():
|
def repo_command():
|
||||||
sys.stdout.write(f"""
|
repo_cmd_table = Table(show_header=True, header_style=header_title)
|
||||||
{Color.white}Logs subcommands{Color.reset}
|
repo_cmd_table.add_column("Command", style="dim")
|
||||||
{'='*17}
|
repo_cmd_table.add_column("Description")
|
||||||
{Help.usageText.format('logs:<subcommand>')}
|
repo_cmd_table.add_row("profile", "Get a repository's info")
|
||||||
|
repo_cmd_table.add_row("issues", "Return a repository's issues")
|
||||||
|
repo_cmd_table.add_row("forks", "Return a repository's forks")
|
||||||
|
repo_cmd_table.add_row("releases", "Return a repository's releases")
|
||||||
|
repo_cmd_table.add_row("stargazers", "Return a repository's stargazers")
|
||||||
|
repo_cmd_table.add_row("contributors", "Return a repository's contributors")
|
||||||
|
repo_cmd_table.add_row("path_contents", "List contents in a path of a repository")
|
||||||
|
|
||||||
{Color.white}Command Description{Color.reset}
|
syntax = f"{green}repo:<command>{reset}"
|
||||||
------- -----------
|
xprint(f"{usage_text.format(syntax, 'repository investigation(s)')}")
|
||||||
view View logs
|
xprint(repo_cmd_table)
|
||||||
read Read log
|
|
||||||
delete Delete log
|
|
||||||
""")
|
|
||||||
|
|
||||||
def csvCommand():
|
|
||||||
sys.stdout.write(f"""
|
|
||||||
{Color.white}Csv subcommands{Color.reset}
|
|
||||||
{'='*17}
|
|
||||||
{Help.usageText.format('csv:<subcommand>')}
|
|
||||||
|
|
||||||
{Color.white}Command Description{Color.reset}
|
|
||||||
------- -----------
|
|
||||||
view View csv files
|
|
||||||
read Read csv
|
|
||||||
delete Delete csv
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def helpCommand():
|
def logs_command():
|
||||||
sys.stdout.write(f"""
|
logs_cmd_table = Table(show_header=True, header_style=header_title)
|
||||||
{Color.white}Core commands{Color.reset}
|
logs_cmd_table.add_column("Command", style="dim")
|
||||||
{'='*13}
|
logs_cmd_table.add_column("Description")
|
||||||
|
logs_cmd_table.add_row("view", "View logs")
|
||||||
|
logs_cmd_table.add_row("read", "Read log")
|
||||||
|
logs_cmd_table.add_row("delete", "Delete log")
|
||||||
|
logs_cmd_table.add_row("clear", "clear logs")
|
||||||
|
|
||||||
{Color.white}Command Description{Color.reset}
|
syntax = f"{green}logs:<command>{reset}"
|
||||||
------- -----------
|
xprint(f"{usage_text.format(syntax, 'log(s) management')}")
|
||||||
help Help menu
|
xprint(logs_cmd_table)
|
||||||
exit Close session
|
|
||||||
clear Clear screen
|
|
||||||
about Program' info
|
|
||||||
author Developer' info
|
|
||||||
|
|
||||||
|
|
||||||
{Color.white}Help subcommands{Color.reset}
|
def csv_command():
|
||||||
{'='*16}
|
csv_cmd_table = Table(show_header=True, header_style=header_title)
|
||||||
{Help.usageText.format('help:<subcommand>')}
|
csv_cmd_table.add_column("Command", style="dim")
|
||||||
|
csv_cmd_table.add_column("Description")
|
||||||
|
csv_cmd_table.add_row("view", "View csv files")
|
||||||
|
csv_cmd_table.add_row("read", "Read csv")
|
||||||
|
csv_cmd_table.add_row("delete", "Delete csv")
|
||||||
|
csv_cmd_table.add_row("clear", "clear csv files")
|
||||||
|
|
||||||
{Color.white}Command Description{Color.reset}
|
syntax = f"{green}csv:<command>{reset}"
|
||||||
------- -----------
|
xprint(f"{usage_text.format(syntax, 'csv management')}")
|
||||||
csv (coming soon)
|
xprint(csv_cmd_table)
|
||||||
org List all organization investigation commands
|
|
||||||
logs List all logs management commands
|
|
||||||
repo List all repository investigation commands
|
def help_command():
|
||||||
user List all users investigation commands
|
core_cmd_table = Table(show_header=True, header_style=header_title)
|
||||||
search List all target discovery commands
|
core_cmd_table.add_column("Command", style="dim", width=12)
|
||||||
source (beta) List all source code download commands (for developers)
|
core_cmd_table.add_column("Description")
|
||||||
version List all version management commands
|
core_cmd_table.add_row("ls", "List contents of the specified directory")
|
||||||
""")
|
core_cmd_table.add_row("cd", "Move to specified directory")
|
||||||
|
core_cmd_table.add_row("help", "Help menu")
|
||||||
|
core_cmd_table.add_row("exit", "Close session")
|
||||||
|
core_cmd_table.add_row("clear", "Clear screen")
|
||||||
|
core_cmd_table.add_row("about", "Program's info")
|
||||||
|
core_cmd_table.add_row("author", "Developer's info")
|
||||||
|
|
||||||
|
help_sub_cmd_table = Table(show_header=True, header_style=header_title)
|
||||||
|
help_sub_cmd_table.add_column("Command", style="dim", width=12)
|
||||||
|
help_sub_cmd_table.add_column("Description")
|
||||||
|
help_sub_cmd_table.add_row("csv", "List all csv management commands")
|
||||||
|
help_sub_cmd_table.add_row("logs", "List all logs management commands")
|
||||||
|
help_sub_cmd_table.add_row("org", "List all organization investigation commands")
|
||||||
|
help_sub_cmd_table.add_row("user", "List all users investigation commands")
|
||||||
|
help_sub_cmd_table.add_row("repo", "List all repository investigation commands")
|
||||||
|
help_sub_cmd_table.add_row("search", "List all target discovery commands")
|
||||||
|
help_sub_cmd_table.add_row("source", "List all source code download commands (for developers)")
|
||||||
|
|
||||||
|
syntax = f"{green}help:<command>{reset}"
|
||||||
|
xprint(core_cmd_table)
|
||||||
|
xprint(f"\n\n{usage_text.format(syntax, 'octosuite')}")
|
||||||
|
xprint(help_sub_cmd_table)
|
||||||
|
|||||||
@@ -1,25 +1,21 @@
|
|||||||
'''
|
# LogRoller This class is where the main notification strings/messages are held, and are being used in two different
|
||||||
logRoller
|
# cases (they're being used by logging to be written to log files, and being printed out to the screen).
|
||||||
This class is where the main notification strings/messages are held,
|
|
||||||
and are being used in two different cases (they're beig used by logging to be written to log files, and being printed out to the screen).
|
|
||||||
'''
|
ctrl_c = "Session terminated with Ctrl+C."
|
||||||
class logRoller:
|
error = "An error occurred: {}"
|
||||||
Ctrl = 'Session terminated with {}.'
|
session_opened = "Opened new session on {}:{}"
|
||||||
Error = 'An error occurred: {}'
|
session_closed = "Session closed at {}."
|
||||||
sessionOpened = 'Opened new session on {}:{}'
|
viewing_logs = "Viewing logs"
|
||||||
sessionClosed = 'Session closed at {}.'
|
viewing_csv = "Viewing CSV file(s)..."
|
||||||
deletedLog = 'Deleted log: {}'
|
deleted = "Deleted: {}"
|
||||||
readingLog = 'Reading log: {}'
|
reading = "Reading: {}"
|
||||||
viewingLogs = 'Viewing logs...'
|
file_downloading = "Downloading: {}"
|
||||||
fileDownloading = 'Downloading ({})...'
|
file_downloaded = "Downloaded: downloads/{}"
|
||||||
fileDownloaded = 'Downloaded. Saved to downloads/{}'
|
info_not_found = "Information not found: {}, {}, {}"
|
||||||
fileNotFound = 'File ({}) not found.'
|
user_not_found = "User not found: @{}"
|
||||||
infoNotFound = 'Information ({} - {} - {}) not found.'
|
org_not_found = "Organization not found: @{}"
|
||||||
repoNotFound = 'Repository ({}) not found.'
|
repo_or_user_not_found = "Repository or User not found: {}, @{}"
|
||||||
userNotFound = 'User (@{}) not found.'
|
prompt_log_csv = "Would you like to log this output to a .csv file?"
|
||||||
orgNotFound = 'Organization (@{}) not found.'
|
logged_to_csv = "Output logged: {}"
|
||||||
repoOrUserNotFound = 'Repository or user not found ({} - @{}).'
|
limit_output = "Limit '{}' output to how many? (1-100)"
|
||||||
askLogCsv = 'Do you wish to log this output to a .csv file? (Y/n) '
|
|
||||||
loggedToCsv = 'Output logged to {}'
|
|
||||||
loggingSkipped = '.csv logging skipped.'
|
|
||||||
limitInput = ' Limit {} output to how many? (1-100) '
|
|
||||||
|
|||||||
13
octosuite/message_prefixes.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from octosuite.config import red, white, green, yellow, reset
|
||||||
|
|
||||||
|
"""
|
||||||
|
message prefixes that show what
|
||||||
|
a notification in OctoSuite might be all about. This might not be very important or necessary in some cases,
|
||||||
|
but I think it's better to know the severity of the notifications you get in a program.
|
||||||
|
"""
|
||||||
|
PROMPT = f"{white}[{green}PROMPT{white}]{reset}"
|
||||||
|
WARNING = f"{white}[{yellow}WARNING{white}]{reset}"
|
||||||
|
ERROR = f"{white}[{red}ERROR{white}]{reset}"
|
||||||
|
POSITIVE = f"{white}[{green}POSITIVE{white}]{reset}"
|
||||||
|
NEGATIVE = f"{white}[{red}NEGATIVE{white}]{reset}"
|
||||||
|
INFO = f"{white}[{green}INFO{white}]{reset}"
|
||||||
1110
octosuite/octosuite.py
Normal file
@@ -1,15 +0,0 @@
|
|||||||
from octosuite.colors import Color
|
|
||||||
|
|
||||||
'''
|
|
||||||
Attributes
|
|
||||||
*Even here, I couldn't think of a good name.*
|
|
||||||
The Attributes class holds the signs/symbols that show what a notification in OctoSuite might be all about.
|
|
||||||
This might not be very important or necessary in some cases, but I think it's better to know the severerity of the notifications you get in a program.
|
|
||||||
'''
|
|
||||||
class SignVar:
|
|
||||||
prompt = f'{Color.white}[{Color.green} ? {Color.white}]{Color.reset}'
|
|
||||||
warning = f'{Color.white}[{Color.red} ! {Color.white}]{Color.reset}'
|
|
||||||
error = f'{Color.white}[{Color.red} x {Color.white}]{Color.reset}'
|
|
||||||
positive = f'{Color.white}[{Color.green} + {Color.white}]{Color.reset}'
|
|
||||||
negative = f'{Color.white}[{Color.red} - {Color.white}]{Color.reset}'
|
|
||||||
info = f'{Color.white}[{Color.green} * {Color.white}]{Color.reset}'
|
|
||||||
10
setup.py
@@ -5,16 +5,16 @@ with open("README.md", "r", encoding="utf-8") as file:
|
|||||||
|
|
||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
name="octosuite",
|
name="octosuite",
|
||||||
version="2.1.0",
|
version="3.0.0",
|
||||||
author="Richard Mwewa",
|
author="Richard Mwewa",
|
||||||
author_email="richardmwewa@duck.com",
|
author_email="rly0nheart@duck.com",
|
||||||
packages=["octosuite"],
|
packages=["octosuite"],
|
||||||
description="Advanced Github OSINT Framework",
|
description="Advanced Github OSINT Framework",
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
url="https://github.com/rly0nheart/octosuite",
|
url="https://github.com/bellingcat/octosuite",
|
||||||
license="GNU General Public License v3 (GPLv3)",
|
license="GNU General Public License v3 (GPLv3)",
|
||||||
install_requires=["requests"],
|
install_requires=["requests", "rich", "psutil", "pyreadline3"],
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 5 - Production/Stable',
|
'Development Status :: 5 - Production/Stable',
|
||||||
'Intended Audience :: Information Technology',
|
'Intended Audience :: Information Technology',
|
||||||
@@ -25,7 +25,7 @@ setuptools.setup(
|
|||||||
],
|
],
|
||||||
entry_points={
|
entry_points={
|
||||||
"console_scripts": [
|
"console_scripts": [
|
||||||
"octosuite=octosuite.main:onStart",
|
"octosuite=octosuite.main:octosuite",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||