From ed8513fd062f0eb04889be719d720fd4ef487d6e Mon Sep 17 00:00:00 2001 From: "Christopher K. Hoadley" Date: Wed, 26 Dec 2018 21:54:25 -0600 Subject: [PATCH] Update Command Line Interface: Accept List Of User Names, Add Version Revamp command line interface. Allow user to pass a list of user names on the command line. Update readme to illustrate actual usage. Pass debug option in argument list instead of depending on the global variable. This should probably all be reworked to use the logging module. --- README.md | 21 +++++++++-- sherlock.py | 102 +++++++++++++++++++++++++++++++++------------------- 2 files changed, 85 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 467aabb..fbe85fe 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,27 @@ $ pip3 install -r requirements.txt ``` ## Usage -Just run ```python3 sherlock.py``` -All of the accounts found will be stored in a text file with their username (e.g ```user123.txt```) +```bash +$ python3 sherlock.py --help +usage: sherlock.py [-h] [--version] [--verbose] [--quiet] + USERNAMES [USERNAMES ...] + +Sherlock: Find Usernames Across Social Networks (Version 0.1.0) + +positional arguments: + USERNAMES One or more usernames to check with social networks. + +optional arguments: + -h, --help show this help message and exit + --version Display version information and dependencies. + --verbose, -v, -d, --debug + Display extra debugging information. + --quiet, -q Disable debugging information (Default Option). +``` +For example, run ```python3 sherlock.py user123```, and all of the accounts +found will be stored in a text file with the username (e.g ```user123.txt```). ## License MIT License diff --git a/sherlock.py b/sherlock.py index e9e5894..89387be 100644 --- a/sherlock.py +++ b/sherlock.py @@ -1,11 +1,17 @@ +"""Sherlock: Find Usernames Across Social Networks Module + +This module contains the main logic to search for usernames at social +networks. +""" import requests import json import os import sys import re -import argparse -DEBUG = False +module_name = "Sherlock: Find Usernames Across Social Networks" +__version__ = "0.1.0" + # TODO: fix tumblr @@ -19,35 +25,22 @@ def print_error(err, errstr, var, debug = False): else: print (f"\033[37;1m[\033[91;1m-\033[37;1m]\033[91;1m {errstr}\033[93;1m {var}") -def make_request(url, headers, error_type, social_network): +def make_request(url, headers, error_type, social_network, verbose=False): try: r = requests.get(url, headers=headers) if r.status_code: return r, error_type except requests.exceptions.HTTPError as errh: - print_error(errh, "HTTP Error:", social_network, DEBUG) + print_error(errh, "HTTP Error:", social_network, verbose) except requests.exceptions.ConnectionError as errc: - print_error(errc, "Error Connecting:", social_network, DEBUG) + print_error(errc, "Error Connecting:", social_network, verbose) except requests.exceptions.Timeout as errt: - print_error(errt, "Timeout Error:", social_network, DEBUG) + print_error(errt, "Timeout Error:", social_network, verbose) except requests.exceptions.RequestException as err: - print_error(err, "Unknown error:", social_network, DEBUG) + print_error(err, "Unknown error:", social_network, verbose) return None, "" - -def sherlock(username): - # Not sure why, but the banner messes up if i put into one print function - print("\033[37;1m .\"\"\"-.") - print("\033[37;1m / \\") - print("\033[37;1m ____ _ _ _ | _..--'-.") - print("\033[37;1m/ ___|| |__ ___ _ __| | ___ ___| |__ >.`__.-\"\"\;\"`") - print("\033[37;1m\___ \| '_ \ / _ \ '__| |/ _ \ / __| |/ / / /( ^\\") - print("\033[37;1m ___) | | | | __/ | | | (_) | (__| < '-`) =|-.") - print("\033[37;1m|____/|_| |_|\___|_| |_|\___/ \___|_|\_\ /`--.'--' \ .-.") - print("\033[37;1m .'`-._ `.\ | J /") - print("\033[37;1m / `--.| \__/\033[0m") - - print() +def sherlock(username, verbose=False): fname = username+".txt" if os.path.isfile(fname): @@ -58,7 +51,7 @@ def sherlock(username): raw = open("data.json", "r", encoding="utf-8") data = json.load(raw) - # User agent is needed because some sites does not + # User agent is needed because some sites does not # return the correct information because it thinks that # we are bot headers = { @@ -79,24 +72,24 @@ def sherlock(username): print("\033[37;1m[\033[91;1m-\033[37;1m]\033[92;1m {}:\033[93;1m Illegal User Name Format For This Site!".format(social_network)) continue - r, error_type = make_request(url=url, headers=headers, error_type=error_type, social_network=social_network) - + r, error_type = make_request(url=url, headers=headers, error_type=error_type, social_network=social_network, verbose=verbose) + if error_type == "message": error = data.get(social_network).get("errorMsg") # Checks if the error message is in the HTML if not error in r.text: print("\033[37;1m[\033[92;1m+\033[37;1m]\033[92;1m {}:\033[0m".format(social_network), url) - write_to_file(url, fname) - + write_to_file(url, fname) + else: print("\033[37;1m[\033[91;1m-\033[37;1m]\033[92;1m {}:\033[93;1m Not Found!".format(social_network)) - + elif error_type == "status_code": # Checks if the status code of the repsonse is 404 if not r.status_code == 404: print("\033[37;1m[\033[92;1m+\033[37;1m]\033[92;1m {}:\033[0m".format(social_network), url) write_to_file(url, fname) - + else: print("\033[37;1m[\033[91;1m-\033[37;1m]\033[92;1m {}:\033[93;1m Not Found!".format(social_network)) @@ -114,15 +107,52 @@ def sherlock(username): print("\033[1;92m[\033[0m\033[1;77m*\033[0m\033[1;92m] Saved: \033[37;1m{}\033[0m".format(username+".txt")) + return + if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument('username', help='check services with given username') - parser.add_argument("-d", '--debug', help="enable debug mode", action="store_true") + from argparse import ArgumentParser, RawDescriptionHelpFormatter + import platform + + version_string = f"%(prog)s {__version__}\n" + \ + f"{requests.__description__}: {requests.__version__}\n" + \ + f"Python: {platform.python_version()}" + + parser = ArgumentParser(formatter_class=RawDescriptionHelpFormatter, + description=f"{module_name} (Version {__version__})" + ) + parser.add_argument("--version", + action="version", version=version_string, + help="Display version information and dependencies." + ) + parser.add_argument("--verbose", "-v", "-d", "--debug", + action="store_true", dest="verbose", default=False, + help="Display extra debugging information." + ) + parser.add_argument("--quiet", "-q", + action="store_false", dest="verbose", + help="Disable debugging information (Default Option)." + ) + parser.add_argument("username", + nargs='+', metavar='USERNAMES', + action="store", + help="One or more usernames to check with social networks." + ) args = parser.parse_args() - - if args.debug: - DEBUG = True - if args.username: - sherlock(args.username) \ No newline at end of file + #Banner + print( +"""\033[37;1m .\"\"\"-. +\033[37;1m / \\ +\033[37;1m ____ _ _ _ | _..--'-. +\033[37;1m/ ___|| |__ ___ _ __| | ___ ___| |__ >.`__.-\"\"\;\"` +\033[37;1m\___ \| '_ \ / _ \ '__| |/ _ \ / __| |/ / / /( ^\\ +\033[37;1m ___) | | | | __/ | | | (_) | (__| < '-`) =|-. +\033[37;1m|____/|_| |_|\___|_| |_|\___/ \___|_|\_\ /`--.'--' \ .-. +\033[37;1m .'`-._ `.\ | J / +\033[37;1m / `--.| \__/\033[0m""") + + #Run report on all specified users. + for username in args.username: + print() + sherlock(username, verbose=args.verbose)