diff --git a/octosuite/config.py b/octosuite/config.py index 03a0eec..df09398 100644 --- a/octosuite/config.py +++ b/octosuite/config.py @@ -25,14 +25,14 @@ def usage(): octosuite --method user_repos --username - Get Organi[sz]ation Profile Info + Get Organisation Profile Info ----------------------------- - octosuite --method org_profile --organization + octosuite --method org_profile --organisation Get Organi[sz]ation Repos ----------------------------- - octosuite --method org_repos --organization + octosuite --method org_repos --organisation Get Repo Profile Info @@ -134,7 +134,7 @@ def create_parser(): '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('-o', '--organisation', '--organization', help='organisation 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)') diff --git a/octosuite/csv_loggers.py b/octosuite/csv_loggers.py index c518b82..2449f8a 100644 --- a/octosuite/csv_loggers.py +++ b/octosuite/csv_loggers.py @@ -11,14 +11,14 @@ from octosuite.message_prefixes import PROMPT, WARNING, POSITIVE, NEGATIVE, INFO def log_org_profile(response): 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', + 'Is verified?', 'Has organisation projects?', 'Has repository projects?', 'Created at', 'Updated 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()['is_verified'], response.json()['has_organisation_projects'], response.json()['has_repository_projects'], response.json()['created_at'], response.json()['updated_at']] @@ -34,7 +34,7 @@ def log_org_profile(response): # Creating a .csv file of a user' profile def log_user_profile(response): user_profile_fields = ['Profile photo', 'Name', 'Username', 'ID', 'Node ID', 'Bio', 'Blog', 'Location', 'Followers', - 'Following', 'Twitter handle', 'Gists', 'Repositories', 'Organization', 'Is hireable?', + 'Following', 'Twitter handle', 'Gists', 'Repositories', 'organisation', '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'], @@ -184,12 +184,12 @@ def log_repo_contributors(contributor, repo_name): xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}") -# Create .csv for organization' events -def log_repo_events(event, organization): +# Create .csv for organisation' events +def log_repo_events(event, organisation): org_event_fields = ['ID', 'Type', 'Created at', 'Payload'] org_event_row = [event['id'], event['type'], event['created_at'], event['payload']] - with open(os.path.join("output", f"{organization}_event_{event['id']}.csv"), 'w') as file: + with open(os.path.join("output", f"{organisation}_event_{event['id']}.csv"), 'w') as file: write_csv = csv.writer(file) write_csv.writerow(org_event_fields) write_csv.writerow(org_event_row) @@ -198,8 +198,8 @@ def log_repo_events(event, organization): xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}") -# Create .csv for organization' repositories -def log_org_repos(repository, organization): +# Create .csv for organisation' repositories +def log_org_repos(repository, organisation): 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?', @@ -213,7 +213,7 @@ def log_org_repos(repository, organization): repository['has_projects'], repository['has_issues'], repository['has_downloads'], repository['pushed_at'], repository['created_at'], repository['updated_at']] - with open(os.path.join("output", f"{repository['name']}_repository_of_{organization}.csv"), 'w') as file: + with open(os.path.join("output", f"{repository['name']}_repository_of_{organisation}.csv"), 'w') as file: write_csv = csv.writer(file) write_csv.writerow(org_repo_fields) write_csv.writerow(org_repo_row) @@ -335,13 +335,13 @@ def log_user_subscriptions(repository, username): xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}") -# .csv for user organizations -def log_user_orgs(organization, username): +# .csv for user organisations +def log_user_orgs(organisation, 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']] + user_org_row = [organisation['avatar_url'], organisation['login'], organisation['id'], organisation['node_id'], + organisation['url'], organisation['description']] - with open(os.path.join("output", f"{organization['login']}_{username}.csv"), 'w') as file: + with open(os.path.join("output", f"{organisation['login']}_{username}.csv"), 'w') as file: write_csv = csv.writer(file) write_csv.writerow(user_org_fields) write_csv.writerow(user_org_row) diff --git a/octosuite/helper.py b/octosuite/helper.py index e30afcc..0136949 100644 --- a/octosuite/helper.py +++ b/octosuite/helper.py @@ -70,7 +70,7 @@ def user_command(): user_cmd_table.add_row("email", "Return a target's email") 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("orgs", "Return organizations that a target belongs to/owns") + user_cmd_table.add_row("orgs", "Return organisations 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)") @@ -87,13 +87,13 @@ def org_command(): org_cmd_table = Table(show_header=True, header_style=header_title) org_cmd_table.add_column("Command", style="dim") org_cmd_table.add_column("Description") - 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") + org_cmd_table.add_row("profile", "Get a target organisation' profile info") + org_cmd_table.add_row("repos", "Return a target organisation' repositories") + org_cmd_table.add_row("events", "Return a target organisation' events") + org_cmd_table.add_row("member", "Check if a specified user is a public member of the target organisation") syntax = f"{green}org:{reset}" - xprint(f"{usage_text.format(syntax, 'organization investigation(s)')}") + xprint(f"{usage_text.format(syntax, 'organisation investigation(s)')}") xprint(org_cmd_table) @@ -159,7 +159,7 @@ def help_command(): 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("org", "List all organisation 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") diff --git a/octosuite/log_roller.py b/octosuite/log_roller.py index 216b965..a234d52 100644 --- a/octosuite/log_roller.py +++ b/octosuite/log_roller.py @@ -14,7 +14,7 @@ file_downloading = "Downloading: {}" file_downloaded = "Downloaded: downloads/{}" info_not_found = "Information not found: {}, {}, {}" user_not_found = "User not found: @{}" -org_not_found = "Organization not found: @{}" +org_not_found = "organisation not found: @{}" repo_or_user_not_found = "Repository or User not found: {}, @{}" prompt_log_csv = "Would you like to log this output to a .csv file?" logged_to_csv = "Output logged: {}" diff --git a/octosuite/octosuite.py b/octosuite/octosuite.py index 814f4c5..4278772 100644 --- a/octosuite/octosuite.py +++ b/octosuite/octosuite.py @@ -202,7 +202,7 @@ def about(): about_text = f""" OCTOSUITE © 2023 Richard Mwewa -An advanced and lightning fast framework for gathering open-source intelligence on GitHub users and organizations. +An advanced and lightning fast framework for gathering open-source intelligence on GitHub users and organisations. Read the wiki: https://github.com/bellingcat/octosuite/wiki GitHub REST API documentation: https://docs.github.com/rest @@ -338,12 +338,12 @@ class Octosuite: 'sha': 'SHA', 'html_url': 'URL'} - # Organization attributes + # organisation attributes self.org_attrs = ['avatar_url', 'login', 'id', 'node_id', 'email', 'description', 'blog', 'location', 'followers', 'following', 'twitter_username', 'public_gists', 'public_repos', 'type', 'is_verified', - 'has_organization_projects', 'has_repository_projects', 'created_at', 'updated_at'] - # Organization attribute dictionary + 'has_organisation_projects', 'has_repository_projects', 'created_at', 'updated_at'] + # organisation attribute dictionary self.org_attr_dict = {'avatar_url': 'Profile Photo', 'login': 'Username', 'id': 'ID', @@ -359,7 +359,7 @@ class Octosuite: 'public_repos': 'Repositories', 'type': 'Account type', 'is_verified': 'Is verified?', - 'has_organization_projects': 'Has organization projects?', + 'has_organisation_projects': 'Has organisation projects?', 'has_repository_projects': 'Has repository projects?', 'created_at': 'Created at', 'updated_at': 'Updated at'} @@ -435,7 +435,7 @@ class Octosuite: 'twitter_username': 'Twitter Handle', 'public_gists': 'Gists (public)', 'public_repos': 'Repositories (public)', - 'company': 'Organization', + 'company': 'organisation', 'hireable': 'Is hireable?', 'site_admin': 'Is site admin?', 'created_at': 'Joined at', @@ -519,7 +519,7 @@ class Octosuite: 'created_at': 'Created at', 'updated_at': 'Updated at'} - # User organizations attributes + # User organisations attributes self.user_orgs_attrs = ['avatar_url', 'id', 'node_id', 'url', 'description'] self.user_orgs_attr_dict = {'avatar_url': 'Profile Photo', 'id': 'ID', @@ -555,15 +555,15 @@ class Octosuite: xprint(f"{username}: {email}") break - # Fetching organization info + # Fetching organisation info def org_profile(self): - if args.organization: - organization = args.organization + if args.organisation: + organisation = args.organisation else: - organization = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}") - response = requests.get(f"{self.endpoint}/orgs/{organization}") + organisation = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}") + response = requests.get(f"{self.endpoint}/orgs/{organisation}") if response.status_code == 404: - xprint(f"{NEGATIVE} {org_not_found.format(organization)}") + xprint(f"{NEGATIVE} {org_not_found.format(organisation)}") elif response.status_code == 200: org_profile_tree = Tree("\n{response.json()['name']}") for attr in self.org_attrs: @@ -775,17 +775,17 @@ class Octosuite: else: xprint(response.json()) - # Fetching organization repositories + # Fetching organisation repositories def org_repos(self): - if args.organization and args.limit: - organization = args.organization + if args.organisation and args.limit: + organisation = args.organisation limit = args.limit else: - organization = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}") - limit = Prompt.ask(limit_output.format("organization repositories")) - response = requests.get(f"{self.endpoint}/orgs/{organization}/repos?per_page={limit}") + organisation = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}") + limit = Prompt.ask(limit_output.format("organisation repositories")) + response = requests.get(f"{self.endpoint}/orgs/{organisation}/repos?per_page={limit}") if response.status_code == 404: - xprint(f"{NEGATIVE} {org_not_found.format(organization)}") + xprint(f"{NEGATIVE} {org_not_found.format(organisation)}") elif response.status_code == 200: for repository in response.json(): repos_tree = Tree("\n" + repository['full_name']) @@ -794,21 +794,21 @@ class Octosuite: xprint(repos_tree) if args.log_csv or Prompt.ask(f"{PROMPT} {prompt_log_csv}") == "yes": - log_org_repos(repository, organization) + log_org_repos(repository, organisation) else: xprint(response.json()) - # organization events + # organisation events def org_events(self): - if args.organization and args.limit: - organization = args.organization + if args.organisation and args.limit: + organisation = args.organisation limit = args.limit else: - organization = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}") - limit = Prompt.ask(limit_output.format("organization events")) - response = requests.get(f"{self.endpoint}/orgs/{organization}/events?per_page={limit}") + organisation = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}") + limit = Prompt.ask(limit_output.format("organisation events")) + response = requests.get(f"{self.endpoint}/orgs/{organisation}/events?per_page={limit}") if response.status_code == 404: - xprint(f"{NEGATIVE} {org_not_found.format(organization)}") + xprint(f"{NEGATIVE} {org_not_found.format(organisation)}") elif response.status_code == 200: for event in response.json(): events_tree = Tree("\n" + event['id']) @@ -816,21 +816,21 @@ class Octosuite: events_tree.add(f"Created at: {event['created_at']}") xprint(events_tree) xprint(event['payload']) - # log_org_events(event, organization) + # log_org_events(event, organisation) else: xprint(response.json()) - # organization member + # organisation member def org_member(self): - if args.organization and args.username: - organization = args.organization + if args.organisation and args.username: + organisation = args.organisation username = args.username else: - organization = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}") + organisation = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}") username = Prompt.ask(f"{white}@{green}Username{reset}") - response = requests.get(f"{self.endpoint}/orgs/{organization}/public_members/{username}") + response = requests.get(f"{self.endpoint}/orgs/{organisation}/public_members/{username}") if response.status_code == 204: - xprint(f"{POSITIVE} User ({username}) is a public member of the organization -> ({organization})") + xprint(f"{POSITIVE} User ({username}) is a public member of the organisation -> ({organisation})") else: xprint(f"{NEGATIVE} {response.json()['message']}") @@ -882,28 +882,28 @@ class Octosuite: else: xprint(response.json()) - # Fetching a list of organizations that a user owns or belongs to + # Fetching a list of organisations that a user owns or belongs to def user_orgs(self): if args.username and args.limit: username = args.username limit = args.limit else: username = Prompt.ask(f"{white}@{green}Username{reset}") - limit = Prompt.ask(limit_output.format("user organizations")) + limit = Prompt.ask(limit_output.format("user organisations")) response = requests.get(f"{self.endpoint}/users/{username}/orgs?per_page={limit}") if not response.json(): - xprint(f"{NEGATIVE} User ({username}) does not (belong to/own) any organizations.") + xprint(f"{NEGATIVE} User ({username}) does not (belong to/own) any organisations.") elif response.status_code == 404: xprint(f"{NEGATIVE} {user_not_found.format(username)}") elif response.status_code == 200: - for organization in response.json(): - org_tree = Tree("\n" + organization['login']) + for organisation in response.json(): + org_tree = Tree("\n" + organisation['login']) for attr in self.user_orgs_attrs: - org_tree.add(f"{self.user_orgs_attr_dict[attr]}: {organization[attr]}") + org_tree.add(f"{self.user_orgs_attr_dict[attr]}: {organisation[attr]}") xprint(org_tree) if args.log_csv or Confirm.ask(f"\n{PROMPT} {prompt_log_csv}"): - log_user_orgs(organization, username) + log_user_orgs(organisation, username) else: xprint(response.json())