Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions user_scanner/core/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@
"cambly",
"superlive",
"medium",
"cv.ee",
"cv.lv",
"cvkeskus",
"cvonline.lt",
"cvmarket.lv",
"cvmarket.lt",
"jobs.cz",
"pulser",
"hercul",
"seduo.cz",
"seduo.sk",
"payhip",
],
}
Expand Down
30 changes: 30 additions & 0 deletions user_scanner/email_scan/jobs/cv_ee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from user_scanner.core.impersonate import impersonate_request_async
from user_scanner.core.result import Result


_URL = "https://www.cv.ee/api/v1/authentication/password/forgot-password"
_NOT_FOUND = {"errorType": "RESOURCE_NOT_FOUND", "message": "Resource not found."}


async def validate_cv_ee(email: str) -> Result:
"""Request a password reset when the email belongs to an account."""
show_url = "https://www.cv.ee"

try:
response = await impersonate_request_async(
_URL, method="POST", json={"email": email}
)
except Exception as exc:
return Result.error(exc, url=show_url)

if response.status_code == 404:
try:
if response.json() == _NOT_FOUND:
return Result.available(url=show_url)
except ValueError:
pass
if response.status_code == 200 and not response.content:
return Result.taken(url=show_url)
return Result.error(
f"Unexpected password reset response: {response.status_code}", url=show_url
)
30 changes: 30 additions & 0 deletions user_scanner/email_scan/jobs/cv_lv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from user_scanner.core.impersonate import impersonate_request_async
from user_scanner.core.result import Result


_URL = "https://www.cv.lv/api/v1/authentication/password/forgot-password"
_NOT_FOUND = {"errorType": "RESOURCE_NOT_FOUND", "message": "Resource not found."}


async def validate_cv_lv(email: str) -> Result:
"""Request a password reset when the email belongs to an account."""
show_url = "https://www.cv.lv"

try:
response = await impersonate_request_async(
_URL, method="POST", json={"email": email}
)
except Exception as exc:
return Result.error(exc, url=show_url)

if response.status_code == 404:
try:
if response.json() == _NOT_FOUND:
return Result.available(url=show_url)
except ValueError:
pass
if response.status_code == 200 and not response.content:
return Result.taken(url=show_url)
return Result.error(
f"Unexpected password reset response: {response.status_code}", url=show_url
)
50 changes: 50 additions & 0 deletions user_scanner/email_scan/jobs/cvkeskus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import re

from user_scanner.core.impersonate import impersonate_request_async
from user_scanner.core.result import Result


_URL = "https://www.cvkeskus.ee/remind/username"
_NOT_FOUND = "Sisestatud e-posti aadress puudub meie süsteemis."
_MULTIPLE_ACCOUNTS = "Selle e-posti aadressiga on seotud mitu kontot."
_REMINDER_SENT = "Saatsime Sinu kasutajanime meeldetuletuse e-postile:"


async def validate_cvkeskus(email: str) -> Result:
"""Send a username reminder when the email belongs to one account."""
show_url = "https://www.cvkeskus.ee"

try:
page = await impersonate_request_async(_URL)
if page.status_code != 200 or 'id="reminderForm"' not in page.text:
return Result.error(
f"Unexpected reminder page response: {page.status_code}",
url=show_url,
)

token = re.search(
r"name=['\"]csrf_token['\"] value=['\"]([^'\"]+)", page.text
)
if not token:
return Result.error("Could not find reminder CSRF token", url=show_url)

response = await impersonate_request_async(
_URL,
method="POST",
data={"csrf_token": token.group(1), "email": email},
headers={"Referer": _URL},
)
except Exception as exc:
return Result.error(exc, url=show_url)

if response.status_code != 200:
return Result.error(
f"Unexpected reminder response: {response.status_code}", url=show_url
)
if _NOT_FOUND in response.text:
return Result.available(url=show_url)
if _MULTIPLE_ACCOUNTS in response.text:
return Result.taken(url=show_url, extra={"multiple_accounts": True})
if _REMINDER_SENT in response.text:
return Result.taken(url=show_url, extra={"multiple_accounts": False})
return Result.error("Unexpected reminder response body", url=show_url)
48 changes: 48 additions & 0 deletions user_scanner/email_scan/jobs/cvmarket_lt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import re

from user_scanner.core.impersonate import impersonate_request_async
from user_scanner.core.result import Result


_URL = "https://www.cvmarket.lt/remind/username"
_NOT_FOUND = "Su tokiu el. paštu registracijos nėra."
_REMINDER_SENT = "Jeigu su šiuo el. paštu yra paskyrą, jūs turėjote gauti"
_SEND_FAILED = "Laiško nurodytu adresu {} išsiųsti nepavyko!"


async def validate_cvmarket_lt(email: str) -> Result:
"""Send a username reminder when the email belongs to an account."""
show_url = "https://www.cvmarket.lt"

try:
page = await impersonate_request_async(_URL)
if page.status_code != 200 or 'id="reminderForm"' not in page.text:
return Result.error(
f"Unexpected reminder page response: {page.status_code}",
url=show_url,
)

token = re.search(
r"name=['\"]csrf_token['\"] value=['\"]([^'\"]+)", page.text
)
if not token:
return Result.error("Could not find reminder CSRF token", url=show_url)

response = await impersonate_request_async(
_URL,
method="POST",
data={"csrf_token": token.group(1), "email": email},
headers={"Referer": _URL},
)
except Exception as exc:
return Result.error(exc, url=show_url)

if response.status_code != 200:
return Result.error(
f"Unexpected reminder response: {response.status_code}", url=show_url
)
if _NOT_FOUND in response.text:
return Result.available(url=show_url)
if _REMINDER_SENT in response.text or _SEND_FAILED.format(email) in response.text:
return Result.taken(url=show_url)
return Result.error("Unexpected reminder response body", url=show_url)
51 changes: 51 additions & 0 deletions user_scanner/email_scan/jobs/cvmarket_lv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import re

from user_scanner.core.impersonate import impersonate_request_async
from user_scanner.core.result import Result


_URL = "https://www.cvmarket.lv/remind/username"
_NOT_FOUND = "Trūkst e-pasta adreses!"
_REMINDER_SENT = "Ja esat reģistrējies portālā ar norādīto e-pasta adresi"
_RECENT_REQUEST = (
"Pēdējās stundas laikā paroles maiņas pieprasījumu šai e-pasta "
"adresei jau tika saņemts."
)


async def validate_cvmarket_lv(email: str) -> Result:
"""Send a username reminder when the email belongs to an account."""
show_url = "https://www.cvmarket.lv"

try:
page = await impersonate_request_async(_URL)
if page.status_code != 200 or 'id="reminderForm"' not in page.text:
return Result.error(
f"Unexpected reminder page response: {page.status_code}",
url=show_url,
)

token = re.search(
r"name=['\"]csrf_token['\"] value=['\"]([^'\"]+)", page.text
)
if not token:
return Result.error("Could not find reminder CSRF token", url=show_url)

response = await impersonate_request_async(
_URL,
method="POST",
data={"csrf_token": token.group(1), "email": email},
headers={"Referer": _URL},
)
except Exception as exc:
return Result.error(exc, url=show_url)

if response.status_code != 200:
return Result.error(
f"Unexpected reminder response: {response.status_code}", url=show_url
)
if _NOT_FOUND in response.text:
return Result.available(url=show_url)
if _REMINDER_SENT in response.text or _RECENT_REQUEST in response.text:
return Result.taken(url=show_url)
return Result.error("Unexpected reminder response body", url=show_url)
30 changes: 30 additions & 0 deletions user_scanner/email_scan/jobs/cvonline_lt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from user_scanner.core.impersonate import impersonate_request_async
from user_scanner.core.result import Result


_URL = "https://www.cvonline.lt/api/v1/authentication/password/forgot-password"
_NOT_FOUND = {"errorType": "RESOURCE_NOT_FOUND", "message": "Resource not found."}


async def validate_cvonline_lt(email: str) -> Result:
"""Request a password reset when the email belongs to an account."""
show_url = "https://www.cvonline.lt"

try:
response = await impersonate_request_async(
_URL, method="POST", json={"email": email}
)
except Exception as exc:
return Result.error(exc, url=show_url)

if response.status_code == 404:
try:
if response.json() == _NOT_FOUND:
return Result.available(url=show_url)
except ValueError:
pass
if response.status_code == 200 and not response.content:
return Result.taken(url=show_url)
return Result.error(
f"Unexpected password reset response: {response.status_code}", url=show_url
)
31 changes: 31 additions & 0 deletions user_scanner/email_scan/jobs/dirbam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from user_scanner.core.impersonate import impersonate_request_async
from user_scanner.core.result import Result


_URL = "https://www.dirbam.lt/patikrinti/el-pastas"


async def validate_dirbam(email: str) -> Result:
"""Check Dirbam's email validator without creating an account."""
show_url = "https://www.dirbam.lt"

try:
response = await impersonate_request_async(_URL, params={"email": email})
except Exception as exc:
return Result.error(exc, url=show_url)

if response.status_code != 200:
return Result.error(
f"Unexpected validation response: {response.status_code}", url=show_url
)

try:
result = response.json()
except ValueError:
return Result.error("Unexpected validation response body", url=show_url)

if result == "Paskyra su tokių el.paštu jau yra":
return Result.taken(url=show_url)
if result == "true":
return Result.available(url=show_url)
return Result.error("Unexpected validation response body", url=show_url)
40 changes: 40 additions & 0 deletions user_scanner/email_scan/jobs/hercul.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from urllib.parse import quote

from user_scanner.core.impersonate import impersonate_request_async
from user_scanner.core.result import Result


_API = "https://api.hercul.hr/api/auth"


async def validate_hercul(email: str) -> Result:
"""Request a password reset when the email belongs to an account."""
show_url = "https://app.hercul.hr"

try:
availability = await impersonate_request_async(
f"{_API}/email-available/{quote(email, safe='')}"
)
data = availability.json()
is_available = data.get("isAvailable") if isinstance(data, dict) else None
if availability.status_code != 200 or not isinstance(is_available, bool):
return Result.error(
f"Unexpected email availability response: {availability.status_code}",
url=show_url,
)
if is_available:
return Result.available(url=show_url)

response = await impersonate_request_async(
f"{_API}/users/reset-password",
method="POST",
json={"email": email},
)
except Exception as exc:
return Result.error(exc, url=show_url)

if response.status_code == 200 and not response.content:
return Result.taken(url=show_url)
return Result.error(
f"Unexpected password reset response: {response.status_code}", url=show_url
)
48 changes: 48 additions & 0 deletions user_scanner/email_scan/jobs/jobs_cz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import re

from user_scanner.core.impersonate import impersonate_request_async
from user_scanner.core.result import Result


_URL = "https://www.jobs.cz/obnova-hesla/"
_NOT_FOUND = "Zadaný e-mail není registrovaný."
_SENT = "Posíláme odkaz pro obnovení hesla"


async def validate_jobs_cz(email: str) -> Result:
"""Request a password reset when the email belongs to an account."""
show_url = "https://www.jobs.cz"

try:
page = await impersonate_request_async(_URL)
token = re.search(
r'name="user_email\[_token\]" value="([^"]+)"', page.text
)
if not token:
return Result.error("Could not find password reset token", url=show_url)

response = await impersonate_request_async(
_URL,
method="POST",
data={
"user_email[email]": email,
"user_email[submit]": "",
"user_email[_token]": token.group(1),
},
allow_redirects=True,
)
except Exception as exc:
return Result.error(exc, url=show_url)

if response.status_code == 403:
return Result.error("Rate limited by Jobs.cz", url=show_url)
if response.status_code != 200:
return Result.error(
f"Unexpected password reset response: {response.status_code}",
url=show_url,
)
if _NOT_FOUND in response.text:
return Result.available(url=show_url)
if _SENT in response.text:
return Result.taken(url=show_url)
return Result.error("Unexpected password reset response body", url=show_url)
Loading
Loading