Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e2a4f6b66 | |||
| 2b985b57ad | |||
| ed0865363f | |||
| 43a354b235 | |||
| aa5c3b0010 | |||
| 2df7c61be8 | |||
| 61aae782ee | |||
| 6eaec5cccd | |||
| dca64e35d3 | |||
| 2e2248a8a6 | |||
| a9960ff9a4 | |||
| d731f715bf | |||
| 271608fb22 | |||
| eb79980c33 | |||
| e2a225697f | |||
| 173ae5b824 | |||
| dcb935337c | |||
| ed883ad7c8 | |||
| a68ea46fb4 | |||
| ed73b175d7 | |||
| a192cb4bfe | |||
| 32fde9bfc6 | |||
| 4656d95702 |
@@ -20,6 +20,7 @@ jobs:
|
|||||||
# Checkout the base branch but fetch all history to avoid a second fetch call
|
# Checkout the base branch but fetch all history to avoid a second fetch call
|
||||||
ref: ${{ github.base_ref }}
|
ref: ${{ github.base_ref }}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
@@ -90,11 +91,11 @@ jobs:
|
|||||||
# --- The rest of the steps below are unchanged ---
|
# --- The rest of the steps below are unchanged ---
|
||||||
|
|
||||||
- name: Validate modified targets
|
- name: Validate modified targets
|
||||||
if: steps.discover-modified.outputs.changed_targets != ''
|
env:
|
||||||
continue-on-error: true
|
CHANGED_TARGETS: ${{ steps.discover-modified.outputs.changed_targets }}
|
||||||
run: |
|
run: |
|
||||||
poetry run pytest -q --tb no -rA -m validate_targets -n 20 \
|
poetry run pytest -q --tb no -rA -m validate_targets -n 20 \
|
||||||
--chunked-sites "${{ steps.discover-modified.outputs.changed_targets }}" \
|
--chunked-sites "$CHANGED_TARGETS" \
|
||||||
--junitxml=validation_results.xml
|
--junitxml=validation_results.xml
|
||||||
|
|
||||||
- name: Prepare validation summary
|
- name: Prepare validation summary
|
||||||
|
|||||||
+15
-25
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
Community-maintained packages are available for Debian (>= 13), Ubuntu (>= 22.10), Homebrew, Kali, and BlackArch. These packages are not directly supported or maintained by the Sherlock Project.
|
Community-maintained packages are available for Debian (>= 13), Ubuntu (>= 22.10), Homebrew, Kali, and BlackArch. These packages are not directly supported or maintained by the Sherlock Project.
|
||||||
|
|
||||||
See all alternative installation methods [here](https://sherlockproject.xyz/installation)
|
See all alternative installation methods [here](https://sherlockproject.xyz/installation).
|
||||||
|
|
||||||
## General usage
|
## General usage
|
||||||
|
|
||||||
@@ -51,51 +51,41 @@ Accounts found will be stored in an individual text file with the corresponding
|
|||||||
|
|
||||||
```console
|
```console
|
||||||
$ sherlock --help
|
$ sherlock --help
|
||||||
usage: sherlock [-h] [--version] [--verbose] [--folderoutput FOLDEROUTPUT]
|
usage: sherlock [-h] [--version] [--verbose] [--folderoutput FOLDEROUTPUT] [--output OUTPUT] [--csv] [--xlsx] [--site SITE_NAME] [--proxy PROXY_URL] [--dump-response]
|
||||||
[--output OUTPUT] [--tor] [--unique-tor] [--csv] [--xlsx]
|
[--json JSON_FILE] [--timeout TIMEOUT] [--print-all] [--print-found] [--no-color] [--browse] [--local] [--nsfw] [--txt] [--ignore-exclusions]
|
||||||
[--site SITE_NAME] [--proxy PROXY_URL] [--json JSON_FILE]
|
|
||||||
[--timeout TIMEOUT] [--print-all] [--print-found] [--no-color]
|
|
||||||
[--browse] [--local] [--nsfw]
|
|
||||||
USERNAMES [USERNAMES ...]
|
USERNAMES [USERNAMES ...]
|
||||||
|
|
||||||
Sherlock: Find Usernames Across Social Networks (Version 0.14.3)
|
Sherlock: Find Usernames Across Social Networks (Version 0.16.0)
|
||||||
|
|
||||||
positional arguments:
|
positional arguments:
|
||||||
USERNAMES One or more usernames to check with social networks.
|
USERNAMES One or more usernames to check with social networks. Check similar usernames using {?} (replace to '_', '-', '.').
|
||||||
Check similar usernames using {?} (replace to '_', '-', '.').
|
|
||||||
|
|
||||||
optional arguments:
|
options:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
--version Display version information and dependencies.
|
--version Display version information and dependencies.
|
||||||
--verbose, -v, -d, --debug
|
--verbose, -v, -d, --debug
|
||||||
Display extra debugging information and metrics.
|
Display extra debugging information and metrics.
|
||||||
--folderoutput FOLDEROUTPUT, -fo FOLDEROUTPUT
|
--folderoutput FOLDEROUTPUT, -fo FOLDEROUTPUT
|
||||||
If using multiple usernames, the output of the results will be
|
If using multiple usernames, the output of the results will be saved to this folder.
|
||||||
saved to this folder.
|
|
||||||
--output OUTPUT, -o OUTPUT
|
--output OUTPUT, -o OUTPUT
|
||||||
If using single username, the output of the result will be saved
|
If using single username, the output of the result will be saved to this file.
|
||||||
to this file.
|
|
||||||
--tor, -t Make requests over Tor; increases runtime; requires Tor to be
|
|
||||||
installed and in system path.
|
|
||||||
--unique-tor, -u Make requests over Tor with new Tor circuit after each request;
|
|
||||||
increases runtime; requires Tor to be installed and in system
|
|
||||||
path.
|
|
||||||
--csv Create Comma-Separated Values (CSV) File.
|
--csv Create Comma-Separated Values (CSV) File.
|
||||||
--xlsx Create the standard file for the modern Microsoft Excel
|
--xlsx Create the standard file for the modern Microsoft Excel spreadsheet (xlsx).
|
||||||
spreadsheet (xlsx).
|
--site SITE_NAME Limit analysis to just the listed sites. Add multiple options to specify more than one site.
|
||||||
--site SITE_NAME Limit analysis to just the listed sites. Add multiple options to
|
|
||||||
specify more than one site.
|
|
||||||
--proxy PROXY_URL, -p PROXY_URL
|
--proxy PROXY_URL, -p PROXY_URL
|
||||||
Make requests over a proxy. e.g. socks5://127.0.0.1:1080
|
Make requests over a proxy. e.g. socks5://127.0.0.1:1080
|
||||||
|
--dump-response Dump the HTTP response to stdout for targeted debugging.
|
||||||
--json JSON_FILE, -j JSON_FILE
|
--json JSON_FILE, -j JSON_FILE
|
||||||
Load data from a JSON file or an online, valid, JSON file.
|
Load data from a JSON file or an online, valid, JSON file. Upstream PR numbers also accepted.
|
||||||
--timeout TIMEOUT Time (in seconds) to wait for response to requests (Default: 60)
|
--timeout TIMEOUT Time (in seconds) to wait for response to requests (Default: 60)
|
||||||
--print-all Output sites where the username was not found.
|
--print-all Output sites where the username was not found.
|
||||||
--print-found Output sites where the username was found.
|
--print-found Output sites where the username was found (also if exported as file).
|
||||||
--no-color Don't color terminal output
|
--no-color Don't color terminal output
|
||||||
--browse, -b Browse to all results on default browser.
|
--browse, -b Browse to all results on default browser.
|
||||||
--local, -l Force the use of the local data.json file.
|
--local, -l Force the use of the local data.json file.
|
||||||
--nsfw Include checking of NSFW sites from default list.
|
--nsfw Include checking of NSFW sites from default list.
|
||||||
|
--txt Enable creation of a txt file
|
||||||
|
--ignore-exclusions Ignore upstream exclusions (may return more false positives)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ source = "init"
|
|||||||
|
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "sherlock-project"
|
name = "sherlock-project"
|
||||||
version = "0.16.0"
|
version = "0.16.1"
|
||||||
description = "Hunt down social media accounts by username across social networks"
|
description = "Hunt down social media accounts by username across social networks"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
authors = [
|
authors = [
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ class QueryNotify:
|
|||||||
|
|
||||||
self.result = result
|
self.result = result
|
||||||
|
|
||||||
# return
|
|
||||||
|
|
||||||
def start(self, message=None):
|
def start(self, message=None):
|
||||||
"""Notify Start.
|
"""Notify Start.
|
||||||
@@ -56,7 +55,6 @@ class QueryNotify:
|
|||||||
Nothing.
|
Nothing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# return
|
|
||||||
|
|
||||||
def update(self, result):
|
def update(self, result):
|
||||||
"""Notify Update.
|
"""Notify Update.
|
||||||
@@ -75,7 +73,6 @@ class QueryNotify:
|
|||||||
|
|
||||||
self.result = result
|
self.result = result
|
||||||
|
|
||||||
# return
|
|
||||||
|
|
||||||
def finish(self, message=None):
|
def finish(self, message=None):
|
||||||
"""Notify Finish.
|
"""Notify Finish.
|
||||||
@@ -94,7 +91,6 @@ class QueryNotify:
|
|||||||
Nothing.
|
Nothing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# return
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Convert Object To String.
|
"""Convert Object To String.
|
||||||
@@ -137,7 +133,6 @@ class QueryNotifyPrint(QueryNotify):
|
|||||||
self.print_all = print_all
|
self.print_all = print_all
|
||||||
self.browse = browse
|
self.browse = browse
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def start(self, message):
|
def start(self, message):
|
||||||
"""Notify Start.
|
"""Notify Start.
|
||||||
@@ -163,7 +158,6 @@ class QueryNotifyPrint(QueryNotify):
|
|||||||
# An empty line between first line and the result(more clear output)
|
# An empty line between first line and the result(more clear output)
|
||||||
print('\r')
|
print('\r')
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def countResults(self):
|
def countResults(self):
|
||||||
"""This function counts the number of results. Every time the function is called,
|
"""This function counts the number of results. Every time the function is called,
|
||||||
@@ -238,7 +232,7 @@ class QueryNotifyPrint(QueryNotify):
|
|||||||
Fore.WHITE + "]" +
|
Fore.WHITE + "]" +
|
||||||
Fore.GREEN + f" {self.result.site_name}:" +
|
Fore.GREEN + f" {self.result.site_name}:" +
|
||||||
Fore.YELLOW + f" {msg}")
|
Fore.YELLOW + f" {msg}")
|
||||||
|
|
||||||
elif result.status == QueryStatus.WAF:
|
elif result.status == QueryStatus.WAF:
|
||||||
if self.print_all:
|
if self.print_all:
|
||||||
print(Style.BRIGHT + Fore.WHITE + "[" +
|
print(Style.BRIGHT + Fore.WHITE + "[" +
|
||||||
@@ -254,10 +248,9 @@ class QueryNotifyPrint(QueryNotify):
|
|||||||
f"Unknown Query Status '{result.status}' for site '{self.result.site_name}'"
|
f"Unknown Query Status '{result.status}' for site '{self.result.site_name}'"
|
||||||
)
|
)
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def finish(self, message="The processing has been finished."):
|
def finish(self, message="The processing has been finished."):
|
||||||
"""Notify Start.
|
"""Notify Finish.
|
||||||
Will print the last line to the standard output.
|
Will print the last line to the standard output.
|
||||||
Keyword Arguments:
|
Keyword Arguments:
|
||||||
self -- This object.
|
self -- This object.
|
||||||
|
|||||||
@@ -159,6 +159,7 @@
|
|||||||
"errorType": "status_code",
|
"errorType": "status_code",
|
||||||
"url": "https://www.artstation.com/{}",
|
"url": "https://www.artstation.com/{}",
|
||||||
"urlMain": "https://www.artstation.com/",
|
"urlMain": "https://www.artstation.com/",
|
||||||
|
"urlProbe": "https://www.artstation.com/users/{}.json",
|
||||||
"username_claimed": "Blue"
|
"username_claimed": "Blue"
|
||||||
},
|
},
|
||||||
"Asciinema": {
|
"Asciinema": {
|
||||||
@@ -404,6 +405,13 @@
|
|||||||
"urlMain": "https://carbonmade.com/",
|
"urlMain": "https://carbonmade.com/",
|
||||||
"username_claimed": "jenny"
|
"username_claimed": "jenny"
|
||||||
},
|
},
|
||||||
|
"Carrd": {
|
||||||
|
"errorType": "status_code",
|
||||||
|
"regexCheck": "^[a-zA-Z0-9_-]{3,50}$",
|
||||||
|
"url": "https://{}.carrd.co/",
|
||||||
|
"urlMain": "https://carrd.co/",
|
||||||
|
"username_claimed": "blue"
|
||||||
|
},
|
||||||
"Career.habr": {
|
"Career.habr": {
|
||||||
"errorMsg": "<h1>\u041e\u0448\u0438\u0431\u043a\u0430 404</h1>",
|
"errorMsg": "<h1>\u041e\u0448\u0438\u0431\u043a\u0430 404</h1>",
|
||||||
"errorType": "message",
|
"errorType": "message",
|
||||||
@@ -602,10 +610,9 @@
|
|||||||
"username_claimed": "blue"
|
"username_claimed": "blue"
|
||||||
},
|
},
|
||||||
"Cracked Forum": {
|
"Cracked Forum": {
|
||||||
"errorMsg": "The member you specified is either invalid or doesn't exist",
|
"errorType": "status_code",
|
||||||
"errorType": "message",
|
"url": "https://cracked.ax/{}",
|
||||||
"url": "https://cracked.sh/{}",
|
"urlMain": "https://cracked.ax/",
|
||||||
"urlMain": "https://cracked.sh/",
|
|
||||||
"username_claimed": "Blue"
|
"username_claimed": "Blue"
|
||||||
},
|
},
|
||||||
"Credly": {
|
"Credly": {
|
||||||
@@ -952,7 +959,8 @@
|
|||||||
"username_claimed": "blue"
|
"username_claimed": "blue"
|
||||||
},
|
},
|
||||||
"GeeksforGeeks": {
|
"GeeksforGeeks": {
|
||||||
"errorType": "status_code",
|
"errorMsg": "false | GeeksforGeeks Profile",
|
||||||
|
"errorType": "message",
|
||||||
"url": "https://auth.geeksforgeeks.org/user/{}",
|
"url": "https://auth.geeksforgeeks.org/user/{}",
|
||||||
"urlMain": "https://www.geeksforgeeks.org/",
|
"urlMain": "https://www.geeksforgeeks.org/",
|
||||||
"username_claimed": "adam"
|
"username_claimed": "adam"
|
||||||
@@ -1526,7 +1534,8 @@
|
|||||||
"username_claimed": "lottiefiles"
|
"username_claimed": "lottiefiles"
|
||||||
},
|
},
|
||||||
"LushStories": {
|
"LushStories": {
|
||||||
"errorType": "status_code",
|
"errorType": "response_url",
|
||||||
|
"errorUrl": "https://www.lushstories.com/login",
|
||||||
"isNSFW": true,
|
"isNSFW": true,
|
||||||
"url": "https://www.lushstories.com/profile/{}",
|
"url": "https://www.lushstories.com/profile/{}",
|
||||||
"urlMain": "https://www.lushstories.com/",
|
"urlMain": "https://www.lushstories.com/",
|
||||||
@@ -2279,6 +2288,13 @@
|
|||||||
"urlMain": "https://sourceforge.net/",
|
"urlMain": "https://sourceforge.net/",
|
||||||
"username_claimed": "blue"
|
"username_claimed": "blue"
|
||||||
},
|
},
|
||||||
|
"SpaceHey": {
|
||||||
|
"errorType": "message",
|
||||||
|
"errorMsg": "Not Found (Error 404) | SpaceHey",
|
||||||
|
"url": "https://spacehey.com/{}",
|
||||||
|
"urlMain": "https://spacehey.com/",
|
||||||
|
"username_claimed": "blue"
|
||||||
|
},
|
||||||
"SoylentNews": {
|
"SoylentNews": {
|
||||||
"errorMsg": "The user you requested does not exist, no matter how much you wish this might be the case.",
|
"errorMsg": "The user you requested does not exist, no matter how much you wish this might be the case.",
|
||||||
"errorType": "message",
|
"errorType": "message",
|
||||||
@@ -2376,6 +2392,13 @@
|
|||||||
"urlMain": "https://www.strava.com/",
|
"urlMain": "https://www.strava.com/",
|
||||||
"username_claimed": "blue"
|
"username_claimed": "blue"
|
||||||
},
|
},
|
||||||
|
"Substack": {
|
||||||
|
"errorType": "status_code",
|
||||||
|
"regexCheck": "^[a-zA-Z0-9][a-zA-Z0-9_-]{1,60}$",
|
||||||
|
"url": "https://{}.substack.com/",
|
||||||
|
"urlMain": "https://substack.com/",
|
||||||
|
"username_claimed": "green"
|
||||||
|
},
|
||||||
"SublimeForum": {
|
"SublimeForum": {
|
||||||
"errorType": "status_code",
|
"errorType": "status_code",
|
||||||
"url": "https://forum.sublimetext.com/u/{}",
|
"url": "https://forum.sublimetext.com/u/{}",
|
||||||
@@ -2827,8 +2850,10 @@
|
|||||||
},
|
},
|
||||||
"akniga": {
|
"akniga": {
|
||||||
"errorType": "status_code",
|
"errorType": "status_code",
|
||||||
|
"errorCode": 404,
|
||||||
|
"request_method": "GET",
|
||||||
"url": "https://akniga.org/profile/{}",
|
"url": "https://akniga.org/profile/{}",
|
||||||
"urlMain": "https://akniga.org/profile/blue/",
|
"urlMain": "https://akniga.org/",
|
||||||
"username_claimed": "blue"
|
"username_claimed": "blue"
|
||||||
},
|
},
|
||||||
"authorSTREAM": {
|
"authorSTREAM": {
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ def get_response(request_future, error_type, social_network):
|
|||||||
except requests.exceptions.RequestException as err:
|
except requests.exceptions.RequestException as err:
|
||||||
error_context = "Unknown Error"
|
error_context = "Unknown Error"
|
||||||
exception_text = str(err)
|
exception_text = str(err)
|
||||||
|
except UnicodeError as err:
|
||||||
|
error_context = "Encoding Error"
|
||||||
|
exception_text = str(err)
|
||||||
|
|
||||||
return response, error_context, exception_text
|
return response, error_context, exception_text
|
||||||
|
|
||||||
@@ -675,16 +678,6 @@ def main():
|
|||||||
help="Include checking of NSFW sites from default list.",
|
help="Include checking of NSFW sites from default list.",
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO deprecated in favor of --txt, retained for workflow compatibility, to be removed
|
|
||||||
# in future release
|
|
||||||
parser.add_argument(
|
|
||||||
"--no-txt",
|
|
||||||
action="store_true",
|
|
||||||
dest="no_txt",
|
|
||||||
default=False,
|
|
||||||
help="Disable creation of a txt file - WILL BE DEPRECATED",
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--txt",
|
"--txt",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import requests
|
|||||||
import secrets
|
import secrets
|
||||||
|
|
||||||
|
|
||||||
MANIFEST_URL = "https://raw.githubusercontent.com/sherlock-project/sherlock/master/sherlock_project/resources/data.json"
|
MANIFEST_URL = "https://data.sherlockproject.xyz"
|
||||||
EXCLUSIONS_URL = "https://raw.githubusercontent.com/sherlock-project/sherlock/refs/heads/exclusions/false_positive_exclusions.txt"
|
EXCLUSIONS_URL = "https://raw.githubusercontent.com/sherlock-project/sherlock/refs/heads/exclusions/false_positive_exclusions.txt"
|
||||||
|
|
||||||
class SiteInformation:
|
class SiteInformation:
|
||||||
@@ -121,11 +121,6 @@ class SitesInformation:
|
|||||||
# users from creating issue about false positives which has already been fixed or having outdated data
|
# users from creating issue about false positives which has already been fixed or having outdated data
|
||||||
data_file_path = MANIFEST_URL
|
data_file_path = MANIFEST_URL
|
||||||
|
|
||||||
# Ensure that specified data file has correct extension.
|
|
||||||
if not data_file_path.lower().endswith(".json"):
|
|
||||||
raise FileNotFoundError(f"Incorrect JSON file extension for data file '{data_file_path}'.")
|
|
||||||
|
|
||||||
# if "http://" == data_file_path[:7].lower() or "https://" == data_file_path[:8].lower():
|
|
||||||
if data_file_path.lower().startswith("http"):
|
if data_file_path.lower().startswith("http"):
|
||||||
# Reference is to a URL.
|
# Reference is to a URL.
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
"""Tests for handling usernames with special/unicode characters."""
|
||||||
|
|
||||||
|
from concurrent.futures import Future
|
||||||
|
|
||||||
|
from sherlock_project.sherlock import get_response
|
||||||
|
|
||||||
|
|
||||||
|
def _make_future_with_exception(exc):
|
||||||
|
"""Create a Future that raises the given exception."""
|
||||||
|
future = Future()
|
||||||
|
future.set_exception(exc)
|
||||||
|
return future
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_response_handles_unicode_decode_error():
|
||||||
|
"""Regression test for issue #2730.
|
||||||
|
|
||||||
|
Usernames with special characters (e.g. 'Émile') can trigger a
|
||||||
|
UnicodeDecodeError inside the requests library during redirect
|
||||||
|
handling. This must not crash the program.
|
||||||
|
"""
|
||||||
|
future = _make_future_with_exception(
|
||||||
|
UnicodeDecodeError("utf-8", b"\xe9", 0, 1, "invalid continuation byte")
|
||||||
|
)
|
||||||
|
response, error_context, exception_text = get_response(
|
||||||
|
request_future=future,
|
||||||
|
error_type=["status_code"],
|
||||||
|
social_network="TestSite",
|
||||||
|
)
|
||||||
|
assert response is None
|
||||||
|
assert error_context == "Encoding Error"
|
||||||
|
assert "utf-8" in exception_text
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_response_handles_unicode_encode_error():
|
||||||
|
"""UnicodeEncodeError should also be caught (subclass of UnicodeError)."""
|
||||||
|
future = _make_future_with_exception(
|
||||||
|
UnicodeEncodeError("ascii", "É", 0, 1, "ordinal not in range(128)")
|
||||||
|
)
|
||||||
|
response, error_context, exception_text = get_response(
|
||||||
|
request_future=future,
|
||||||
|
error_type=["status_code"],
|
||||||
|
social_network="TestSite",
|
||||||
|
)
|
||||||
|
assert response is None
|
||||||
|
assert error_context == "Encoding Error"
|
||||||
|
assert "ascii" in exception_text
|
||||||
+3
-3
@@ -4,7 +4,7 @@ from sherlock_interactives import Interactives
|
|||||||
from sherlock_interactives import InteractivesSubprocessError
|
from sherlock_interactives import InteractivesSubprocessError
|
||||||
|
|
||||||
def test_remove_nsfw(sites_obj):
|
def test_remove_nsfw(sites_obj):
|
||||||
nsfw_target: str = 'Pornhub'
|
nsfw_target: str = 'Xvideos'
|
||||||
assert nsfw_target in {site.name: site.information for site in sites_obj}
|
assert nsfw_target in {site.name: site.information for site in sites_obj}
|
||||||
sites_obj.remove_nsfw_sites()
|
sites_obj.remove_nsfw_sites()
|
||||||
assert nsfw_target not in {site.name: site.information for site in sites_obj}
|
assert nsfw_target not in {site.name: site.information for site in sites_obj}
|
||||||
@@ -12,8 +12,8 @@ def test_remove_nsfw(sites_obj):
|
|||||||
|
|
||||||
# Parametrized sites should *not* include Motherless, which is acting as the control
|
# Parametrized sites should *not* include Motherless, which is acting as the control
|
||||||
@pytest.mark.parametrize('nsfwsites', [
|
@pytest.mark.parametrize('nsfwsites', [
|
||||||
['Pornhub'],
|
['Xvideos'],
|
||||||
['Pornhub', 'Xvideos'],
|
['Xvideos', 'Erome'],
|
||||||
])
|
])
|
||||||
def test_nsfw_explicit_selection(sites_obj, nsfwsites):
|
def test_nsfw_explicit_selection(sites_obj, nsfwsites):
|
||||||
for site in nsfwsites:
|
for site in nsfwsites:
|
||||||
|
|||||||
Reference in New Issue
Block a user