torbot 1.2__py3.6.egg
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- EGG-INFO/PKG-INFO +11 -0
- EGG-INFO/SOURCES.txt +23 -0
- EGG-INFO/dependency_links.txt +1 -0
- EGG-INFO/native_libs.txt +1 -0
- EGG-INFO/not-zip-safe +1 -0
- EGG-INFO/requires.txt +8 -0
- EGG-INFO/scripts/torBot.py +188 -0
- EGG-INFO/top_level.txt +2 -0
- modules/__init__.py +0 -0
- modules/__pycache__/__init__.cpython-36.pyc +0 -0
- modules/__pycache__/bcolors.cpython-36.pyc +0 -0
- modules/__pycache__/getemails.cpython-36.pyc +0 -0
- modules/__pycache__/getweblinks.cpython-36.pyc +0 -0
- modules/__pycache__/go_linker.cpython-36.pyc +0 -0
- modules/__pycache__/info.cpython-36.pyc +0 -0
- modules/__pycache__/pagereader.cpython-36.pyc +0 -0
- modules/__pycache__/savefile.cpython-36.pyc +0 -0
- modules/__pycache__/updater.cpython-36.pyc +0 -0
- modules/bcolors.py +14 -0
- modules/getemails.py +41 -0
- modules/getweblinks.py +136 -0
- modules/go_get_urls.so +0 -0
- modules/go_linker.py +26 -0
- modules/info.py +101 -0
- modules/pagereader.py +109 -0
- modules/savefile.py +24 -0
- modules/updater.py +48 -0
- tests/__init__.py +0 -0
- tests/__pycache__/__init__.cpython-36.pyc +0 -0
- tests/__pycache__/test_getemails.cpython-36.pyc +0 -0
- tests/__pycache__/test_getweblinks.cpython-36.pyc +0 -0
- tests/__pycache__/test_pagereader.cpython-36.pyc +0 -0
- tests/__pycache__/test_savetofile.cpython-36.pyc +0 -0
- tests/test_getemails.py +20 -0
- tests/test_getweblinks.py +25 -0
- tests/test_pagereader.py +69 -0
- tests/test_savetofile.py +40 -0
EGG-INFO/PKG-INFO
ADDED
EGG-INFO/SOURCES.txt
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
setup.py
|
|
2
|
+
torBot
|
|
3
|
+
torBot.py
|
|
4
|
+
modules/__init__.py
|
|
5
|
+
modules/bcolors.py
|
|
6
|
+
modules/getemails.py
|
|
7
|
+
modules/getweblinks.py
|
|
8
|
+
modules/go_get_urls.so
|
|
9
|
+
modules/go_linker.py
|
|
10
|
+
modules/info.py
|
|
11
|
+
modules/pagereader.py
|
|
12
|
+
modules/savefile.py
|
|
13
|
+
modules/updater.py
|
|
14
|
+
tests/__init__.py
|
|
15
|
+
tests/test_getemails.py
|
|
16
|
+
tests/test_getweblinks.py
|
|
17
|
+
tests/test_pagereader.py
|
|
18
|
+
tests/test_savetofile.py
|
|
19
|
+
torBot.egg-info/PKG-INFO
|
|
20
|
+
torBot.egg-info/SOURCES.txt
|
|
21
|
+
torBot.egg-info/dependency_links.txt
|
|
22
|
+
torBot.egg-info/requires.txt
|
|
23
|
+
torBot.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
EGG-INFO/native_libs.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
modules/go_get_urls.so
|
EGG-INFO/not-zip-safe
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
EGG-INFO/requires.txt
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import socket
|
|
3
|
+
import socks
|
|
4
|
+
from modules import (bcolors, getemails, pagereader, getweblinks, updater,
|
|
5
|
+
info, go_linker, savefile)
|
|
6
|
+
|
|
7
|
+
# TorBot VERSION
|
|
8
|
+
__VERSION = "1.2"
|
|
9
|
+
LOCALHOST = "127.0.0.1"
|
|
10
|
+
PORT = 9050
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def connect(address, port):
|
|
14
|
+
""" Establishes connection to port
|
|
15
|
+
|
|
16
|
+
Assumes port is bound to localhost, if host that port is bound to changes
|
|
17
|
+
then change the port
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
address: address for port to bound to
|
|
21
|
+
port: Establishes connect to this port
|
|
22
|
+
"""
|
|
23
|
+
socks.set_default_proxy(socks.PROXY_TYPE_SOCKS5, address, port)
|
|
24
|
+
socket.socket = socks.socksocket # Monkey Patch our socket to tor socket
|
|
25
|
+
|
|
26
|
+
def getaddrinfo(*args):
|
|
27
|
+
"""
|
|
28
|
+
Overloads socket function for std socket library
|
|
29
|
+
Check socket.getaddrinfo() documentation to understand parameters.
|
|
30
|
+
Simple description below:
|
|
31
|
+
argument - explanation (actual value)
|
|
32
|
+
socket.AF_INET - the type of address the socket can speak to (IPV4)
|
|
33
|
+
sock.SOCK_STREAM - creates a stream connecton rather than packets
|
|
34
|
+
6 - protocol being used is TCP
|
|
35
|
+
Last two arguments should be a tuple containing the address and port
|
|
36
|
+
"""
|
|
37
|
+
return [(socket.AF_INET, socket.SOCK_STREAM, 6,
|
|
38
|
+
'', (args[0], args[1]))]
|
|
39
|
+
socket.getaddrinfo = getaddrinfo
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def header():
|
|
43
|
+
"""
|
|
44
|
+
Prints out header ASCII art
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
b_color = bcolors.Bcolors()
|
|
48
|
+
D3DSEC = b_color.FAIL + " D3DSEC " + b_color.WHITE
|
|
49
|
+
INS1DE = b_color.FAIL + " INS1DE " + b_color.WHITE
|
|
50
|
+
|
|
51
|
+
header = r"""
|
|
52
|
+
{WHITE}
|
|
53
|
+
######################################################
|
|
54
|
+
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWMMMMMMMMMMMMM
|
|
55
|
+
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWMMMMMMMMMMMMMM
|
|
56
|
+
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXNWWWWWMMMMMMMMMM
|
|
57
|
+
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWX0KXXKKXWMMMMMMMMMMM
|
|
58
|
+
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNNKOkOOkOXWMMMMMMMMMMMMM
|
|
59
|
+
MMMMMMMMMMMMMMMMMMMMMMMMMMMMNX0kdodoxKWMMMMMMMMMMMMMMM
|
|
60
|
+
MMMMMMMMMMMMMMMMMMMMMMMMMMMW0doccloONMWWMMMMMMMMMMMMMM
|
|
61
|
+
MMMMMMMMMMMMMMMMMMMMMMMMMMMKl;;:cxKWMMMMMMMMMMMMMMMMMM
|
|
62
|
+
MMMMMMMMMMMMMMMMMMMMMMWKOXNx;,,cONMMMMMMMMMMMMMMMMMMMM
|
|
63
|
+
MMMMMMMMMMMMMMMMMMMMMMMXdxKk:',lONMMMM{D3DSEC}MMMMMMMM
|
|
64
|
+
MMMMMMMMMMMMMMMMMMMMMMMMOo0NOdxc,kMMMM{INS1DE}MMMMMMMM
|
|
65
|
+
MMMMMMMMMMMMMMMMMMMMMMMMOcONOxkx;dWMMMMMMMMMMMMMMMMMMM
|
|
66
|
+
MMMMMMMMMMMMMMMMMMMMMMNkcdXXOkxkd:oXMMMMMMMMMMMMMMMMMM
|
|
67
|
+
MMMMMMMMMMMMMMMMMMMNOoclONNX00OkOxc:lkXWMMMMMMMMMMMMMM
|
|
68
|
+
MMMMMMMMMMMMMMMMN0olld0NWNNX0O00kxkxl:;ckXMWWMMMMMMMMM
|
|
69
|
+
MMMMMMMMMMMWMMNxccd0NNNNNXNXOkOK0dodxdo:,;o0WMMMMMMMMM
|
|
70
|
+
MMMMMMMMMMMMNk:ckXNNWNXXXXNXOOOOK0oloooooc,'oKMMMMMMMM
|
|
71
|
+
MMMMMMMMMMMXc;xXNNNXKXXXNNWKOO0Ok0x:clllllc:.,OWMMMMMM
|
|
72
|
+
MMMMMMMMMMX:;0WNNX00XNNNNNNKOO0KkkOc,ccccccc:.'OWMMMMM
|
|
73
|
+
MMMMMMMMMNl,ONNN0OXNNNNNXXNKOkOK0xkl':c::::::;.;KMMMMM
|
|
74
|
+
MMMMMMMMM0,lNWXO0NNNNXKKXXNXO0Ok0Oxl',:;;;;;;;..dMMMMM
|
|
75
|
+
MMMMMMMMMk,xWNOONNNX00XNNNWKOO0OkOxc'';;,,,,,,'.cMMMMM
|
|
76
|
+
MMMMMMMMMx,xWKkKWNXOKNWNNNX0xxOKxxx:..,,,,,''''.cMMMMM
|
|
77
|
+
MMMMMMMMM0,oWXkOWXOKNNNNN00Xkdx0kdd;..,'''''''..oMMMMM
|
|
78
|
+
MMMMMMMMMNl;0W0kKKkKWNNN0ONNOxdOOll,..'''......,0MMMMM
|
|
79
|
+
MMMMMMMMMMK::KN0kKOkNNWXk0WX0kdxkc:............xWMMMMM
|
|
80
|
+
MMMMMMMMMMMKl:kX0k0kONWNOONX0koxd:,..........'kWMMMMMM
|
|
81
|
+
MMMMMMMMMMMMNxccxOkkxkKWKx0NOoooc'..........lKWMMMMMMM
|
|
82
|
+
MMMMMMMMMMMMMWNklccclldk0OxOdcc;. .......;oKWWMMMMMMMM
|
|
83
|
+
MMMMMMMMMMMMMMMMWXOdl:::;cc;'... ..',:lx0NMMMMMMMMMMMM
|
|
84
|
+
MMMMMMMMMMMMMMMMMMMMMNKOkxddolloodk0XWMMMMMMMMMMMMMMMM
|
|
85
|
+
{FAIL} + {BOLD}
|
|
86
|
+
__ ____ ____ __ ______
|
|
87
|
+
/ /_/ __ \/ __ \/ /_ ____/_ __/
|
|
88
|
+
/ __/ / / / /_/ / __ \/ __ \/ /
|
|
89
|
+
/ /_/ /_/ / _, _/ /_/ / /_/ / /
|
|
90
|
+
\__/\____/_/ |_/_____/\____/_/ V{VERSION}
|
|
91
|
+
{FAIL} + {On_Black}
|
|
92
|
+
#######################################################
|
|
93
|
+
# TorBot - A python Tor Crawler #
|
|
94
|
+
# GitHub : https://github.com/DedsecInside/TorBot #
|
|
95
|
+
# Help : use -h for help text #
|
|
96
|
+
#######################################################
|
|
97
|
+
{FAIL} + "LICENSE: GNU Public License" + {END}""".format(
|
|
98
|
+
D3DSEC=D3DSEC, INS1DE=INS1DE, FAIL=b_color.FAIL,
|
|
99
|
+
BOLD=b_color.BOLD, VERSION=__VERSION, END=b_color.ENDC,
|
|
100
|
+
On_Black=b_color.On_Black, WHITE=b_color.WHITE
|
|
101
|
+
)
|
|
102
|
+
print(header)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def main(conn=False, link=False):
|
|
106
|
+
if conn:
|
|
107
|
+
connect(LOCALHOST, PORT)
|
|
108
|
+
|
|
109
|
+
parser = argparse.ArgumentParser()
|
|
110
|
+
parser.add_argument("-v", "--version",
|
|
111
|
+
action="store_true",
|
|
112
|
+
help="Show current version of TorBot.")
|
|
113
|
+
parser.add_argument("--update",
|
|
114
|
+
action="store_true",
|
|
115
|
+
help="Update TorBot to the latest stable version")
|
|
116
|
+
parser.add_argument("-q", "--quiet",
|
|
117
|
+
action="store_true")
|
|
118
|
+
parser.add_argument("-u", "--url",
|
|
119
|
+
help="Specifiy a website link to crawl")
|
|
120
|
+
parser.add_argument("-s", "--save",
|
|
121
|
+
action="store_true",
|
|
122
|
+
help="Save results in a file")
|
|
123
|
+
parser.add_argument("-m", "--mail",
|
|
124
|
+
action="store_true",
|
|
125
|
+
help="Get e-mail addresses from the crawled sites")
|
|
126
|
+
parser.add_argument("-e", "--extension",
|
|
127
|
+
action='append',
|
|
128
|
+
dest='extension',
|
|
129
|
+
default=[],
|
|
130
|
+
help=' '.join(("Specifiy additional website extensions",
|
|
131
|
+
"to the list(.com , .org etc)")))
|
|
132
|
+
parser.add_argument("-l", "--live",
|
|
133
|
+
action="store_true",
|
|
134
|
+
help="Check if websites are live or not (slow)")
|
|
135
|
+
parser.add_argument("-i", "--info",
|
|
136
|
+
action="store_true",
|
|
137
|
+
help=' '.join(("Info displays basic info of the",
|
|
138
|
+
"scanned site, (very slow)")))
|
|
139
|
+
args = parser.parse_args()
|
|
140
|
+
|
|
141
|
+
link = args.url
|
|
142
|
+
|
|
143
|
+
# If flag is -v, --update, -q/--quiet then user only runs that operation
|
|
144
|
+
# because these are single flags only
|
|
145
|
+
if args.version:
|
|
146
|
+
print("TorBot Version:" + __VERSION)
|
|
147
|
+
exit()
|
|
148
|
+
if args.update:
|
|
149
|
+
updater.updateTor()
|
|
150
|
+
exit()
|
|
151
|
+
if not args.quiet:
|
|
152
|
+
header()
|
|
153
|
+
# If url flag is set then check for accompanying flag set. Only one
|
|
154
|
+
# additional flag can be set with -u/--url flag
|
|
155
|
+
if args.url:
|
|
156
|
+
print("Tor IP Address :", pagereader.get_ip())
|
|
157
|
+
html_content, response = pagereader.read_first_page(link)
|
|
158
|
+
# -m/--mail
|
|
159
|
+
if args.mail:
|
|
160
|
+
emails = getemails.getMails(html_content)
|
|
161
|
+
print(emails)
|
|
162
|
+
if args.save:
|
|
163
|
+
savefile.saveJson('Emails', emails)
|
|
164
|
+
# -i/--info
|
|
165
|
+
elif args.info:
|
|
166
|
+
info.executeAll(link, html_content, response)
|
|
167
|
+
if args.save:
|
|
168
|
+
print('Nothing to save.\n')
|
|
169
|
+
else:
|
|
170
|
+
# Golang library is now being used
|
|
171
|
+
links = go_linker.GetLinks(link, LOCALHOST, PORT, 15, 1)
|
|
172
|
+
return links
|
|
173
|
+
# links = getweblinks.get_links(soup=html_content, ext=args.extension, live=args.live)
|
|
174
|
+
if args.save:
|
|
175
|
+
savefile.saveJson("Links", links)
|
|
176
|
+
else:
|
|
177
|
+
print("usage: torBot.py [-h] [-v] [--update] [-q] [-u URL] [-s] [-m] [-e EXTENSION] [-l] [-i]")
|
|
178
|
+
|
|
179
|
+
print("\n\n")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
if __name__ == '__main__':
|
|
183
|
+
|
|
184
|
+
try:
|
|
185
|
+
main(conn=True)
|
|
186
|
+
|
|
187
|
+
except KeyboardInterrupt:
|
|
188
|
+
print("Interrupt received! Exiting cleanly...")
|
EGG-INFO/top_level.txt
ADDED
modules/__init__.py
ADDED
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
modules/bcolors.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class Bcolors:
|
|
2
|
+
|
|
3
|
+
def __init__(self):
|
|
4
|
+
self.HEADER = '\033[95m'
|
|
5
|
+
self.OKBLUE = '\033[94m'
|
|
6
|
+
self.OKGREEN = '\033[92m'
|
|
7
|
+
self.WARNING = '\033[93m'
|
|
8
|
+
self.FAIL = '\033[91m'
|
|
9
|
+
self.ENDC = '\033[0m'
|
|
10
|
+
self.BOLD = '\033[1m'
|
|
11
|
+
self.UNDERLINE = '\033[4m'
|
|
12
|
+
self.WHITE = '\033[97m'
|
|
13
|
+
self.On_Black = '\033[40m'
|
|
14
|
+
self.On_Red = '\033[41m'
|
modules/getemails.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from modules.bcolors import Bcolors
|
|
2
|
+
from bs4 import BeautifulSoup
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def getMails(soup):
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
Searches for <a href> tags for links then checks if link contains the
|
|
9
|
+
substring 'mailto' indicating that it's an email. If it is determined
|
|
10
|
+
to be an email then the link is split and the username is appeneded to
|
|
11
|
+
the list
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
soup: BeautifulSoup isntance that will be used for parsing
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
emails: list of email IDs
|
|
18
|
+
"""
|
|
19
|
+
b_colors = Bcolors()
|
|
20
|
+
|
|
21
|
+
if isinstance(type(soup), type(BeautifulSoup)):
|
|
22
|
+
|
|
23
|
+
emails = []
|
|
24
|
+
links = soup.find_all('a')
|
|
25
|
+
for ref in links:
|
|
26
|
+
url = ref.get('href')
|
|
27
|
+
if url and 'mailto' in url:
|
|
28
|
+
"""Split email address on"""
|
|
29
|
+
email_addr = url.split(':')
|
|
30
|
+
if (len(email_addr) > 1):
|
|
31
|
+
emails.append(email_addr[1])
|
|
32
|
+
|
|
33
|
+
"""Pretty print output as below"""
|
|
34
|
+
print ('')
|
|
35
|
+
print (b_colors.OKGREEN+'Mails Found - '+b_colors.ENDC+str(len(emails)))
|
|
36
|
+
print ('-------------------------------')
|
|
37
|
+
|
|
38
|
+
return emails
|
|
39
|
+
|
|
40
|
+
else:
|
|
41
|
+
raise('Method parameter is not of instance BeautifulSoup')
|
modules/getweblinks.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import requests
|
|
3
|
+
import tldextract
|
|
4
|
+
|
|
5
|
+
from modules import pagereader
|
|
6
|
+
from bs4 import BeautifulSoup
|
|
7
|
+
from modules.bcolors import Bcolors
|
|
8
|
+
from requests.exceptions import ConnectionError, HTTPError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def valid_url(url, extensions=False):
|
|
12
|
+
"""Checks for any valid url using regular expression matching
|
|
13
|
+
|
|
14
|
+
Matches all possible url patterns with the url that is passed and
|
|
15
|
+
returns True if it is a url and returns False if it is not.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
url: string representing url to be checked
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
bool: True if valid url format and False if not
|
|
22
|
+
"""
|
|
23
|
+
pattern = r"^https?:\/\/(www\.)?([a-z,A-Z,0-9]*)\.([a-z, A-Z]+)(.*)"
|
|
24
|
+
regex = re.compile(pattern)
|
|
25
|
+
if not extensions:
|
|
26
|
+
if regex.match(url):
|
|
27
|
+
return True
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
parts = tldextract.extract(url)
|
|
31
|
+
valid_sites = list()
|
|
32
|
+
for ext in extensions:
|
|
33
|
+
if regex.match(url) and '.'+parts.suffix in ext:
|
|
34
|
+
valid_sites.append(url)
|
|
35
|
+
return valid_sites
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def valid_onion_url(url):
|
|
39
|
+
"""Checks for valid onion url using regular expression matching
|
|
40
|
+
|
|
41
|
+
Only matches onion urls
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
url: string representing url to be checked
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
bool: True if valid onion url format, False if not
|
|
48
|
+
"""
|
|
49
|
+
pattern = r"^https?:\/\/(www\.)?([a-z,A-Z,0-9]*)\.onion/(.*)"
|
|
50
|
+
regex = re.compile(pattern)
|
|
51
|
+
if regex.match(url):
|
|
52
|
+
return True
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def is_link_alive(link):
|
|
57
|
+
"""Generator that yields links as they come
|
|
58
|
+
|
|
59
|
+
Uses head request because it uses less bandwith than get and timeout is
|
|
60
|
+
set to 10 seconds and then link is automatically declared as dead.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
link: link to be tested
|
|
64
|
+
colors: object containing colors for link
|
|
65
|
+
|
|
66
|
+
Yields:
|
|
67
|
+
string: link with either no color or red which indicates failure
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
resp = requests.head(link, timeout=10)
|
|
72
|
+
resp.raise_for_status()
|
|
73
|
+
return True
|
|
74
|
+
except (ConnectionError, HTTPError):
|
|
75
|
+
return False
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def add_green(link):
|
|
79
|
+
colors = Bcolors()
|
|
80
|
+
return '\t' + colors.OKGREEN + link + colors.ENDC
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def add_red(link):
|
|
84
|
+
colors = Bcolors()
|
|
85
|
+
return '\t' + colors.On_Red + link + colors.ENDC
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_links(soup, ext=False, live=False):
|
|
89
|
+
"""
|
|
90
|
+
Searches through all <a ref> (hyperlinks) tags and stores them in a
|
|
91
|
+
list then validates if the url is formatted correctly.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
soup: BeautifulSoup instance currently being used.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
websites: List of websites that were found
|
|
98
|
+
"""
|
|
99
|
+
b_colors = Bcolors()
|
|
100
|
+
if isinstance(soup, BeautifulSoup):
|
|
101
|
+
websites = []
|
|
102
|
+
|
|
103
|
+
links = soup.find_all('a')
|
|
104
|
+
for ref in links:
|
|
105
|
+
url = ref.get('href')
|
|
106
|
+
if ext:
|
|
107
|
+
if url and valid_url(url, ext):
|
|
108
|
+
websites.append(url)
|
|
109
|
+
else:
|
|
110
|
+
if url and valid_onion_url(url):
|
|
111
|
+
websites.append(url)
|
|
112
|
+
|
|
113
|
+
"""Pretty print output as below"""
|
|
114
|
+
print(''.join((b_colors.OKGREEN,
|
|
115
|
+
'Websites Found - ', b_colors.ENDC, str(len(websites)))))
|
|
116
|
+
print('------------------------------------')
|
|
117
|
+
|
|
118
|
+
if live:
|
|
119
|
+
for link in websites:
|
|
120
|
+
if is_link_alive(link):
|
|
121
|
+
coloredlink = add_green(link)
|
|
122
|
+
page = pagereader.read_page(link)
|
|
123
|
+
if page is not None and page.title is not None:
|
|
124
|
+
print_row(coloredlink, page.title.string)
|
|
125
|
+
else:
|
|
126
|
+
coloredlink = add_red(link)
|
|
127
|
+
print_row(coloredlink, "Not found")
|
|
128
|
+
|
|
129
|
+
return websites
|
|
130
|
+
|
|
131
|
+
else:
|
|
132
|
+
raise(Exception('Method parameter is not of instance BeautifulSoup'))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def print_row(url, description):
|
|
136
|
+
print("%-80s %-30s" % (url, description))
|
modules/go_get_urls.so
ADDED
|
Binary file
|
modules/go_linker.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
|
|
3
|
+
from ctypes import cdll, c_char_p, c_longlong, c_int, Structure
|
|
4
|
+
|
|
5
|
+
dll_path = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + "go_get_urls.so"
|
|
6
|
+
go_linker = cdll.LoadLibrary(dll_path)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class GoString(Structure):
|
|
10
|
+
_fields_ = [("p", c_char_p), ("n", c_longlong)]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
go_linker.GetLinks.argtypes = [GoString, GoString, GoString, c_int, c_int]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def GetLinks(url, addr, port, timeout, extensions):
|
|
17
|
+
|
|
18
|
+
url = url.encode('utf-8')
|
|
19
|
+
addr = addr.encode('utf-8')
|
|
20
|
+
port = str(port).encode('utf-8')
|
|
21
|
+
|
|
22
|
+
go_linker.GetLinks(GoString(url, len(url)),
|
|
23
|
+
GoString(addr, len(addr)),
|
|
24
|
+
GoString(port, len(port)),
|
|
25
|
+
timeout,
|
|
26
|
+
extensions)
|
modules/info.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
|
|
3
|
+
from urllib.parse import urlsplit
|
|
4
|
+
from termcolor import cprint
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def executeAll(target, soup, response):
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
get_robots_txt(target)
|
|
11
|
+
except Exception:
|
|
12
|
+
cprint("No robots.txt file Found!""blue")
|
|
13
|
+
try:
|
|
14
|
+
get_dot_git(target)
|
|
15
|
+
except Exception:
|
|
16
|
+
cprint("Error !""red")
|
|
17
|
+
try:
|
|
18
|
+
get_dot_svn(target)
|
|
19
|
+
except Exception:
|
|
20
|
+
cprint("Error""red")
|
|
21
|
+
try:
|
|
22
|
+
get_dot_htaccess(target)
|
|
23
|
+
except Exception:
|
|
24
|
+
cprint("Error""red")
|
|
25
|
+
try:
|
|
26
|
+
get_webpage_description(soup)
|
|
27
|
+
except Exception:
|
|
28
|
+
cprint("Error""red")
|
|
29
|
+
try:
|
|
30
|
+
get_headers(response)
|
|
31
|
+
except Exception:
|
|
32
|
+
cprint("Error""red")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_headers(response):
|
|
36
|
+
print('''
|
|
37
|
+
RESPONSE HEADERS
|
|
38
|
+
__________________
|
|
39
|
+
''')
|
|
40
|
+
for key, val in response.headers.items():
|
|
41
|
+
print('*', key, ':', val)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_robots_txt(target):
|
|
45
|
+
cprint("[*]Checking for Robots.txt"'yellow')
|
|
46
|
+
url = target
|
|
47
|
+
target = "{0.scheme}://{0.netloc}/".format(urlsplit(url))
|
|
48
|
+
requests.get(target+"/robots.txt")
|
|
49
|
+
cprint(r'blue')
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_dot_git(target):
|
|
53
|
+
cprint("[*]Checking for .git folder"'yellow')
|
|
54
|
+
url = target
|
|
55
|
+
target = "{0.scheme}://{0.netloc}/".format(urlsplit(url))
|
|
56
|
+
req = requests.get(target+"/.git/")
|
|
57
|
+
r = req.status_code
|
|
58
|
+
if r == 200:
|
|
59
|
+
cprint("Alert!"'red')
|
|
60
|
+
cprint(".git folder exposed publicly"'red')
|
|
61
|
+
else:
|
|
62
|
+
print("NO .git folder found"'blue')
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def get_dot_svn(target):
|
|
66
|
+
cprint("[*]Checking for .svn folder"'yellow')
|
|
67
|
+
url = target
|
|
68
|
+
target = "{0.scheme}://{0.netloc}/".format(urlsplit(url))
|
|
69
|
+
req = requests.get(target+"/.svn/entries")
|
|
70
|
+
r = req.status_code
|
|
71
|
+
if r == 200:
|
|
72
|
+
cprint("Alert!"'red')
|
|
73
|
+
cprint(".SVN folder exposed publicly"'red')
|
|
74
|
+
else:
|
|
75
|
+
cprint("NO .SVN folder found"'blue')
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_dot_htaccess(target):
|
|
79
|
+
cprint("[*]Checking for .htaccess"'yellow')
|
|
80
|
+
url = target
|
|
81
|
+
target = "{0.scheme}://{0.netloc}/".format(urlsplit(url))
|
|
82
|
+
req = requests.get(target+"/.htaccess")
|
|
83
|
+
statcode = req.status_code
|
|
84
|
+
if statcode == 403:
|
|
85
|
+
cprint("403 Forbidden"'blue')
|
|
86
|
+
elif statcode == 200:
|
|
87
|
+
cprint("Alert!!"'blue')
|
|
88
|
+
cprint(".htaccess file found!"'blue')
|
|
89
|
+
else:
|
|
90
|
+
cprint("Status code"'blue')
|
|
91
|
+
cprint(statcode)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def get_webpage_description(soup):
|
|
95
|
+
cprint("[*]Checking for description meta tag"'yellow')
|
|
96
|
+
metatags = soup.find_all('meta')
|
|
97
|
+
for meta in metatags:
|
|
98
|
+
if meta.has_attr('name'):
|
|
99
|
+
attributes = meta.attrs
|
|
100
|
+
if attributes['name'] == 'description':
|
|
101
|
+
cprint("Page description: " + attributes['content'])
|
modules/pagereader.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
|
|
3
|
+
from bs4 import BeautifulSoup
|
|
4
|
+
from modules.bcolors import Bcolors
|
|
5
|
+
from requests.exceptions import ConnectionError, HTTPError, MissingSchema
|
|
6
|
+
from sys import exit
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def connection_msg(site):
|
|
10
|
+
yield "Attempting to connect to {site}".format(site=site)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def read_first_page(site):
|
|
14
|
+
headers = {'User-Agent':
|
|
15
|
+
'TorBot - Onion crawler | www.github.com/DedSecInside/TorBot'}
|
|
16
|
+
attempts_left = 3
|
|
17
|
+
err = " "
|
|
18
|
+
while attempts_left:
|
|
19
|
+
try:
|
|
20
|
+
if attempts_left == 3:
|
|
21
|
+
print(next(connection_msg(site)))
|
|
22
|
+
response = requests.get(site, headers=headers)
|
|
23
|
+
print("Connection successful.")
|
|
24
|
+
page = BeautifulSoup(response.text, 'html.parser')
|
|
25
|
+
return page, response
|
|
26
|
+
if attempts_left == 2:
|
|
27
|
+
print(next(connection_msg('https://'+site)))
|
|
28
|
+
response = requests.get('https://'+site, headers=headers)
|
|
29
|
+
print("Connection successful.")
|
|
30
|
+
page = BeautifulSoup(response.text, 'html.parser')
|
|
31
|
+
return page, response
|
|
32
|
+
if attempts_left == 1:
|
|
33
|
+
print(next(connection_msg('http://'+site)))
|
|
34
|
+
response = requests.get('http://'+site, headers=headers)
|
|
35
|
+
print("Connection successful.")
|
|
36
|
+
page = BeautifulSoup(response.text, 'html.parser')
|
|
37
|
+
return page, response
|
|
38
|
+
if not attempts_left:
|
|
39
|
+
msg = ''.join(("There has been an {err} while attempting to ",
|
|
40
|
+
"connect to {site}.")).format(err=err, site=site)
|
|
41
|
+
exit(msg)
|
|
42
|
+
|
|
43
|
+
except (HTTPError, MissingSchema, ConnectionError) as e:
|
|
44
|
+
attempts_left -= 1
|
|
45
|
+
err = e
|
|
46
|
+
|
|
47
|
+
if isinstance(err, HTTPError):
|
|
48
|
+
print ("There has been an HTTP error after three attempts.")
|
|
49
|
+
exit (1)
|
|
50
|
+
if isinstance(err, ConnectionError):
|
|
51
|
+
print("Got ConnectionError after three attempts... ",
|
|
52
|
+
"Please check if the TOR service is running or not.")
|
|
53
|
+
exit (1)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def read_page(site):
|
|
57
|
+
headers = {'User-Agent':
|
|
58
|
+
'TorBot - Onion crawler | www.github.com/DedSecInside/TorBot'}
|
|
59
|
+
attempts_left = 3
|
|
60
|
+
err = " "
|
|
61
|
+
while attempts_left:
|
|
62
|
+
try:
|
|
63
|
+
if attempts_left == 3:
|
|
64
|
+
#print(next(connection_msg(site)))
|
|
65
|
+
response = requests.get(site, headers=headers)
|
|
66
|
+
#print("Connection successful.")
|
|
67
|
+
page = BeautifulSoup(response.text, 'html.parser')
|
|
68
|
+
return page
|
|
69
|
+
if attempts_left == 2:
|
|
70
|
+
#print(next(connection_msg('https://'+site)))
|
|
71
|
+
response = requests.get('https://'+site, headers=headers)
|
|
72
|
+
#print("Connection successful.")
|
|
73
|
+
page = BeautifulSoup(response.text, 'html.parser')
|
|
74
|
+
return page
|
|
75
|
+
if attempts_left == 1:
|
|
76
|
+
#print(next(connection_msg('http://'+site)))
|
|
77
|
+
response = requests.get('http://'+site, headers=headers)
|
|
78
|
+
#print("Connection successful.")
|
|
79
|
+
page = BeautifulSoup(response.text, 'html.parser')
|
|
80
|
+
return page
|
|
81
|
+
if not attempts_left:
|
|
82
|
+
msg = ''.join(("There has been an {err} while attempting to ",
|
|
83
|
+
"connect to {site}.")).format(err=err, site=site)
|
|
84
|
+
exit(msg)
|
|
85
|
+
|
|
86
|
+
except (HTTPError, MissingSchema, ConnectionError) as e:
|
|
87
|
+
attempts_left -= 1
|
|
88
|
+
err = e
|
|
89
|
+
|
|
90
|
+
if isinstance(err, HTTPError):
|
|
91
|
+
print("There has been an HTTP error after three attempts.")
|
|
92
|
+
exit (1)
|
|
93
|
+
if isinstance(err, ConnectionError):
|
|
94
|
+
print("There has been a connection error after three attempts.")
|
|
95
|
+
exit (1)
|
|
96
|
+
|
|
97
|
+
def get_ip():
|
|
98
|
+
"""Returns users tor ip address
|
|
99
|
+
|
|
100
|
+
https://check.torproject.org/ tells you if you are using tor and it
|
|
101
|
+
displays your IP address which we scape and return
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
b_colors = Bcolors()
|
|
105
|
+
page = read_first_page('https://check.torproject.org/')[0]
|
|
106
|
+
pg = page.find('strong')
|
|
107
|
+
ip_addr = pg.renderContents()
|
|
108
|
+
|
|
109
|
+
return b_colors.WARNING+b_colors.BOLD+ip_addr.decode("utf-8")+b_colors.ENDC
|
modules/savefile.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def saveJson(datatype, data):
|
|
6
|
+
"""
|
|
7
|
+
Creates json file and stores json
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
datatype: the type of the object being passed
|
|
11
|
+
data = data that is being stored with object
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
timestr = time.strftime("%Y%m%d-%H%M%S")
|
|
15
|
+
file_name = "TorBot-Export-"+datatype+timestr+".json"
|
|
16
|
+
# Json File Creation
|
|
17
|
+
with open(file_name, "w+") as f:
|
|
18
|
+
# Store data in Json format
|
|
19
|
+
output = {datatype: data}
|
|
20
|
+
# Dump output to file
|
|
21
|
+
json.dump(output, f, indent=2)
|
|
22
|
+
|
|
23
|
+
print("\nData will be saved with a File Name :", file_name)
|
|
24
|
+
return file_name
|
modules/updater.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def updateTor():
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
Currently updates Tor by calling terminal commands using subprocess
|
|
8
|
+
Not a great method and will be replaced in the future.
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
print("Checking for latest stable release")
|
|
13
|
+
isGit = subprocess.Popen(
|
|
14
|
+
["git", "branch"],
|
|
15
|
+
stdout=subprocess.PIPE,
|
|
16
|
+
stderr=subprocess.STDOUT)
|
|
17
|
+
output = isGit.stdout.read()
|
|
18
|
+
branch = output[2:8].decode("utf-8")
|
|
19
|
+
print(branch)
|
|
20
|
+
if branch == 'master':
|
|
21
|
+
update = subprocess.Popen(
|
|
22
|
+
["git", "pull", "origin", "master"],
|
|
23
|
+
stdout=subprocess.PIPE,
|
|
24
|
+
stderr=subprocess.STDOUT)
|
|
25
|
+
update_out = update.stdout.read()
|
|
26
|
+
if update_out[90:109].decode("utf-8") == 'Already up-to-date.':
|
|
27
|
+
print("TorBot is already up-to-date.")
|
|
28
|
+
else:
|
|
29
|
+
print("TorBot has succesfully updated to latest stable version.")
|
|
30
|
+
else:
|
|
31
|
+
subprocess.Popen(
|
|
32
|
+
["git", "init"],
|
|
33
|
+
stdout=subprocess.PIPE,
|
|
34
|
+
stderr=subprocess.STDOUT)
|
|
35
|
+
subprocess.Popen(
|
|
36
|
+
["git", "remote", "add", "origin",
|
|
37
|
+
"https://github.com/DedSecInside/TorBoT.git"],
|
|
38
|
+
stdout=subprocess.PIPE,
|
|
39
|
+
stderr=subprocess.STDOUT)
|
|
40
|
+
update = subprocess.Popen(
|
|
41
|
+
["git", "pull", "origin", "dev"],
|
|
42
|
+
stdout=subprocess.PIPE,
|
|
43
|
+
stderr=subprocess.STDOUT)
|
|
44
|
+
update_out = update.stdout.read()
|
|
45
|
+
if update_out[90:109].decode("utf-8") == 'Already up-to-date.':
|
|
46
|
+
print("TorBot is already up-to-date.")
|
|
47
|
+
else:
|
|
48
|
+
print("TorBot has succesfully updated to latest stable version.")
|
tests/__init__.py
ADDED
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
tests/test_getemails.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
PACKAGE_PARENT = '..'
|
|
5
|
+
SCRIPT_DIR = os.path.dirname(os.path.realpath(
|
|
6
|
+
os.path.join(os.getcwd(), os.path.expanduser(__file__))))
|
|
7
|
+
|
|
8
|
+
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))
|
|
9
|
+
|
|
10
|
+
from modules import pagereader, getemails
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_get_emails_successful():
|
|
14
|
+
soup = pagereader.read_first_page('https://www.helloaddress.com/')[0]
|
|
15
|
+
test_emails = ["hello@helloaddress.com"]
|
|
16
|
+
emails = getemails.getMails(soup)
|
|
17
|
+
assert emails == test_emails
|
|
18
|
+
|
|
19
|
+
if __name__ == '__main__':
|
|
20
|
+
test_get_emails_successful()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
import os
|
|
5
|
+
PACKAGE_PARENT = '..'
|
|
6
|
+
SCRIPT_DIR = os.path.dirname(os.path.realpath(
|
|
7
|
+
os.path.join(os.getcwd(), os.path.expanduser(__file__))))
|
|
8
|
+
|
|
9
|
+
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))
|
|
10
|
+
from modules import getweblinks, pagereader
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_get_links_successful():
|
|
14
|
+
soup = pagereader.read_first_page('http://www.whatsmyip.net/')[0]
|
|
15
|
+
data = ['http://aff.ironsocket.com/SH7L',
|
|
16
|
+
'http://aff.ironsocket.com/SH7L',
|
|
17
|
+
'http://wsrs.net/',
|
|
18
|
+
'http://cmsgear.com/']
|
|
19
|
+
|
|
20
|
+
result = getweblinks.get_links(soup, ext=['.com', '.net'])
|
|
21
|
+
assert result == data
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if __name__ == '__main__':
|
|
25
|
+
test_get_links_successful()
|
tests/test_pagereader.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import requests
|
|
3
|
+
import requests_mock
|
|
4
|
+
|
|
5
|
+
from bs4 import BeautifulSoup
|
|
6
|
+
from requests.exceptions import HTTPError, MissingSchema, ConnectionError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture
|
|
10
|
+
def test_read_first_page(site):
|
|
11
|
+
|
|
12
|
+
with requests_mock.Mocker() as m:
|
|
13
|
+
m.get('https://www.test.com', text='This is a dot com site.')
|
|
14
|
+
m.get('https://www.test.org', text='This is a dot org site.')
|
|
15
|
+
m.get('https://www.test.net', text='This is a dot net site.')
|
|
16
|
+
m.get('https://www.test.onion', text='This is a dot onion site.')
|
|
17
|
+
|
|
18
|
+
m.register_uri('GET', 'https://www.test.cannotbefound', exc=HTTPError)
|
|
19
|
+
m.register_uri('GET', 'http://www.test.cannotbefound', exc=HTTPError)
|
|
20
|
+
|
|
21
|
+
headers = {'User-Agent':
|
|
22
|
+
'TorBot - Onion crawler | www.github.com/DedSecInside/TorBot'}
|
|
23
|
+
attempts_left = 3
|
|
24
|
+
err = " "
|
|
25
|
+
|
|
26
|
+
# Removed unnecessary code such as printing
|
|
27
|
+
while attempts_left:
|
|
28
|
+
try:
|
|
29
|
+
if attempts_left == 3:
|
|
30
|
+
response = requests.get(site, headers=headers)
|
|
31
|
+
page = BeautifulSoup(response.text, 'html.parser')
|
|
32
|
+
return str(page)
|
|
33
|
+
if attempts_left == 2:
|
|
34
|
+
response = requests.get('https://'+site, headers=headers)
|
|
35
|
+
page = BeautifulSoup(response.text, 'html.parser')
|
|
36
|
+
return str(page)
|
|
37
|
+
if attempts_left == 1:
|
|
38
|
+
response = requests.get('http://'+site, headers=headers)
|
|
39
|
+
page = BeautifulSoup(response.text, 'html.parser')
|
|
40
|
+
return str(page)
|
|
41
|
+
if not attempts_left:
|
|
42
|
+
raise err
|
|
43
|
+
|
|
44
|
+
except (HTTPError, MissingSchema, ConnectionError) as e:
|
|
45
|
+
err = e
|
|
46
|
+
attempts_left -= 1
|
|
47
|
+
|
|
48
|
+
raise err
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_run():
|
|
52
|
+
urls = ['www.test.com', 'www.test.org', 'www.test.net', 'www.test.onion',
|
|
53
|
+
'www.test.cannotbefound']
|
|
54
|
+
|
|
55
|
+
with pytest.raises(HTTPError):
|
|
56
|
+
for url in urls:
|
|
57
|
+
page = test_read_first_page(url)
|
|
58
|
+
if url[-4:] == '.com':
|
|
59
|
+
assert page == 'This is a dot com site.'
|
|
60
|
+
elif url[-4:] == '.org':
|
|
61
|
+
assert page == 'This is a dot org site.'
|
|
62
|
+
elif url[-4:] == '.net':
|
|
63
|
+
assert page == 'This is a dot net site.'
|
|
64
|
+
elif url[-6:] == '.onion':
|
|
65
|
+
assert page == 'This is a dot onion site.'
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == '__main__':
|
|
69
|
+
test_run()
|
tests/test_savetofile.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
import json
|
|
4
|
+
PACKAGE_PARENT = '..'
|
|
5
|
+
SCRIPT_DIR = os.path.dirname(os.path.realpath(
|
|
6
|
+
os.path.join(os.getcwd(), os.path.expanduser(__file__))))
|
|
7
|
+
|
|
8
|
+
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))
|
|
9
|
+
|
|
10
|
+
from modules import savefile
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_save_links_successful():
|
|
14
|
+
mock_data = ['http://aff.ironsocket.com/SH7L',
|
|
15
|
+
'http://aff.ironsocket.com/SH7L',
|
|
16
|
+
'http://wsrs.net/',
|
|
17
|
+
'http://cmsgear.com/']
|
|
18
|
+
try:
|
|
19
|
+
file_name = savefile.saveJson('Links', mock_data)
|
|
20
|
+
mock_output = {'Links': mock_data}
|
|
21
|
+
|
|
22
|
+
with open('test_file.json', 'w+') as test_file:
|
|
23
|
+
json.dump(mock_output, test_file, indent=2)
|
|
24
|
+
|
|
25
|
+
os.chdir(os.getcwd())
|
|
26
|
+
assert os.path.isfile(file_name) is True
|
|
27
|
+
mock_file = open(file_name, 'r')
|
|
28
|
+
test_file = open('test_file.json', 'r')
|
|
29
|
+
|
|
30
|
+
mock_data = mock_file.read()
|
|
31
|
+
test_data = test_file.read()
|
|
32
|
+
|
|
33
|
+
finally:
|
|
34
|
+
os.remove(file_name)
|
|
35
|
+
os.remove('test_file.json')
|
|
36
|
+
|
|
37
|
+
assert mock_data == test_data
|
|
38
|
+
|
|
39
|
+
if __name__ == '__main__':
|
|
40
|
+
test_save_links_successful()
|