Skip to content

Commit 41b0ea2

Browse files
authored
Merge pull request #17 from mxrch/light-update
1.1.0 update
2 parents 0454565 + d38859d commit 41b0ea2

File tree

10 files changed

+186
-66
lines changed

10 files changed

+186
-66
lines changed

gitfive/lib/commits.py

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import httpx
21
import trio
32
from bs4 import BeautifulSoup
4-
import imagehash
5-
from PIL import Image
63
from alive_progress import alive_bar
74

85

@@ -15,22 +12,31 @@ async def fetch_avatar(runner: GitfiveRunner, email: str, avatar_link: str, user
1512
out: Dict[str, str|bool], check_only: bool):
1613
async with runner.limiters["commits_fetch_avatar"]:
1714
is_target = (username.lower() == runner.target.username.lower())
18-
full_name = await github.fetch_profile_name(runner, username)
19-
_name_str = ""
20-
if full_name:
21-
_name_str = f" [{full_name}]"
22-
if is_target:
23-
if check_only:
24-
runner.rc.print(f"[+] [Target's email] 🐱 {email} -> @{username}{_name_str}", style="cyan")
25-
else:
15+
if check_only:
16+
if is_target:
17+
runner.rc.print(f"[+] [Target's email] 🐱 {email} -> @{username}", style="cyan")
18+
19+
out[email] = {
20+
"avatar": avatar_link,
21+
"username": username,
22+
"is_target": is_target
23+
}
24+
else:
25+
full_name = await github.fetch_profile_name(runner, username)
26+
_name_str = ""
27+
if full_name:
28+
_name_str = f" [{full_name}]"
29+
30+
if is_target:
2631
runner.rc.print(f"[+] [TARGET FOUND] 🐱 {email} -> @{username}{_name_str}", style="green bold")
27-
elif not check_only:
28-
runner.rc.print(f"[+] 🐱 {email} -> @{username}{_name_str}")
29-
out[email] = {
30-
"avatar": avatar_link,
31-
"username": username,
32-
"full_name": full_name,
33-
"is_target": is_target
32+
else:
33+
runner.rc.print(f"[+] 🐱 {email} -> @{username}{_name_str}")
34+
35+
out[email] = {
36+
"avatar": avatar_link,
37+
"full_name": full_name,
38+
"username": username,
39+
"is_target": is_target
3440
}
3541

3642
async def fetch_commits(runner: GitfiveRunner, repo_name: str, emails_index: Dict[str, str],
@@ -73,7 +79,7 @@ async def scrape(runner: GitfiveRunner, repo_name: str, emails_index: Dict[str,
7379
exit("Empty repository.")
7480

7581
if last_hash_trigger in req.text:
76-
total = int(body.select('div.Box-header strong')[0].text.replace(',', ''))
82+
_, total = await get_commits_count(runner, raw_body=req.text)
7783
last_hash = [x for x in body.select('a') if x.text.lower() == "permalink"][0].attrs['href'].split('/')[-1]
7884
else:
7985
exit("Couldn't fetch the last hash.")

gitfive/lib/domain_finder.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ def guess_custom_domain(runner: GitfiveRunner):
1414
hunter = None
1515

1616
# Google
17-
if company != "google": # googlesearch doesn't return Google.com when searching "google"
18-
for url in search(company):
19-
if ("facebook" not in company and "facebook.com" in url) or ("twitter" not in company and "twitter.com" in url) :
20-
continue
21-
google = extract_domain(url)
22-
break
17+
try:
18+
if company != "google": # googlesearch doesn't return Google.com when searching "google"
19+
for url in search(company):
20+
if ("facebook" not in company and "facebook.com" in url) or ("twitter" not in company and "twitter.com" in url) :
21+
continue
22+
google = extract_domain(url)
23+
break
24+
except Exception: # https://github.com/mxrch/GitFive/issues/15
25+
runner.rc.print("[!] Google Search failed, are you using a VPN/Proxy ?", style="italic")
2326

2427
# Hunter.io
2528
req = httpx.get(f"https://hunter.io/v2/domains-suggestion?query={company}")

gitfive/lib/emails_gen.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ def generate(runner: GitfiveRunner, custom_domains_list=[], default_domains_list
3737
else:
3838
usernames.add(sanatize(name.lower()))
3939

40+
for _, email_data in runner.target.ext_contribs.items():
41+
if not (is_local_domain(email_data["domain"]) and email_data["handle"].lower() in config.local_names):
42+
usernames.add(email_data["handle"].lower())
43+
usernames.add(email_data["handle"].split("+")[0].lower())
44+
for name in email_data["names"]:
45+
if name and not (is_local_domain(email_data["domain"]) and name.lower() in config.local_names):
46+
if " " in name:
47+
fullnames.add(sanatize(name.lower()))
48+
else:
49+
usernames.add(sanatize(name.lower()))
50+
4051
for name, name_data in runner.target.near_names.items():
4152
if name:
4253
if " " in name:

gitfive/lib/metamon.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ async def start(runner: GitfiveRunner, emails: List[str]):
140140
if emails_index:
141141
# Checking if commits have been pushed
142142
while True:
143-
found, nb_commits = await get_commits_count(runner, f"https://github.com/{runner.creds.username}/{temp_repo_name}")
143+
found, nb_commits = await get_commits_count(runner, repo_url=f"https://github.com/{runner.creds.username}/{temp_repo_name}")
144144
if found and nb_commits == total_commits_count:
145145
break
146146
sleep(1)

gitfive/lib/objects.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ async def login(self, force=False):
176176
if req.status_code == 302:
177177
if req.cookies.get("logged_in") == "yes":
178178
self.session = {
179-
"user_session": self._as_client.cookies["user_session"],
180-
"__Host-user_session_same_site": self._as_client.cookies["__Host-user_session_same_site"],
179+
"user_session": req.cookies["user_session"],
180+
"__Host-user_session_same_site": req.cookies["__Host-user_session_same_site"],
181181
"_device_id": self._as_client.cookies["_device_id"]
182182
}
183183
self.save_creds()
@@ -205,8 +205,8 @@ async def login(self, force=False):
205205
req = await self._as_client.post("https://github.com/sessions/verified-device", data=data)
206206
if req.cookies.get("logged_in") == "yes":
207207
self.session = {
208-
"user_session": self._as_client.cookies["user_session"],
209-
"__Host-user_session_same_site": self._as_client.cookies["__Host-user_session_same_site"],
208+
"user_session": req.cookies["user_session"],
209+
"__Host-user_session_same_site": req.cookies["__Host-user_session_same_site"],
210210
"_device_id": self._as_client.cookies["_device_id"]
211211
}
212212
self.save_creds()
@@ -256,8 +256,8 @@ async def login(self, force=False):
256256
print("[+] Got confirmation !")
257257

258258
self.session = {
259-
"user_session": self._as_client.cookies["user_session"],
260-
"__Host-user_session_same_site": self._as_client.cookies["__Host-user_session_same_site"],
259+
"user_session": req.cookies["user_session"],
260+
"__Host-user_session_same_site": req.cookies["__Host-user_session_same_site"],
261261
"_device_id": self._as_client.cookies["_device_id"]
262262
}
263263
self.save_creds()
@@ -284,8 +284,8 @@ async def login(self, force=False):
284284
req = await self._as_client.post("https://github.com/sessions/two-factor", data=data)
285285
if req.cookies.get("logged_in") == "yes":
286286
self.session = {
287-
"user_session": self._as_client.cookies["user_session"],
288-
"__Host-user_session_same_site": self._as_client.cookies["__Host-user_session_same_site"],
287+
"user_session": req.cookies["user_session"],
288+
"__Host-user_session_same_site": req.cookies["__Host-user_session_same_site"],
289289
"_device_id": self._as_client.cookies["_device_id"]
290290
}
291291
self.save_creds()
@@ -347,6 +347,7 @@ def __init__(self):
347347
self.updated_at: datetime = None
348348
self.avatar_url = ""
349349
self.is_default_avatar = True
350+
self.nb_ext_contribs = 0
350351

351352
self.potential_friends: Dict[str, Dict[str, int|bool]] = {}
352353
self.repos: List[Dict[str, any]] = []
@@ -360,6 +361,7 @@ def __init__(self):
360361
self.ssh_keys: List[str] = []
361362

362363
self.all_contribs: Dict[str, Dict[str, Dict[str, Dict[str, Set[str]]]]] = {}
364+
self.ext_contribs: Dict[str, Dict[str, Dict[str, Dict[str, Set[str]]]]] = {}
363365
self.internal_contribs: Dict[str, Dict[str, Dict[str, Dict[str, Dict[str, Set[str]]]]]] = {"all": {}, "no_github": {}}
364366
self.usernames_history: Dict[str, Dict[str, Dict[str, Dict[str, Set[str]]]]] = {}
365367
self.near_names: Dict[str, Dict[str, Dict[str, Dict[str, Dict[str, Dict[str, Set[str]]]]]]] = {}
@@ -433,7 +435,7 @@ def __init__(self):
433435
"social_follows": trio.CapacityLimiter(50),
434436
"repos_list": trio.CapacityLimiter(50),
435437
"commits_scrape": trio.CapacityLimiter(50),
436-
"commits_fetch_avatar": trio.CapacityLimiter(4),
438+
"commits_fetch_avatar": trio.CapacityLimiter(1), # https://github.com/mxrch/GitFive/issues/3#issuecomment-1321260050
437439
"orgs_list": trio.CapacityLimiter(50)
438440
}
439441

gitfive/lib/utils.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,11 @@ def change_permissions(path: Path|str):
103103
def show_banner():
104104
rprint(banner)
105105

106-
async def get_commits_count(runner: GitfiveRunner, repo_url: str):
107-
req = await runner.as_client.get(repo_url)
108-
body = BeautifulSoup(req.text, 'html.parser')
106+
async def get_commits_count(runner: GitfiveRunner, repo_url: str="", raw_body: str=""):
107+
if not raw_body:
108+
req = await runner.as_client.get(repo_url)
109+
raw_body = req.text
110+
body = BeautifulSoup(raw_body, 'html.parser')
109111
commits_icon_el = body.find("svg", {"class": "octicon-history"})
110112
if not commits_icon_el:
111113
return False, 0
@@ -144,7 +146,12 @@ def humanize_list(array: List[any]):
144146
return final
145147

146148
def sanatize(text: str) -> str:
147-
deaccented = unidecode(text, "utf-8")
149+
deaccented = ""
150+
try:
151+
deaccented = unidecode(text, "utf-8")
152+
except Exception:
153+
pre_sanatize = ''.join([*filter(lambda x:x.isalpha() or x in "-. ", text)]) # kudos to @n1nj4sec
154+
deaccented = unidecode(pre_sanatize, "utf-8")
148155
return ''.join([*filter(lambda x:x.lower() in string.ascii_lowercase+" ", deaccented)])
149156

150157
def get_gists_stats(runner: GitfiveRunner):
@@ -177,4 +184,11 @@ def unicode_patch(txt: str):
177184
"ç": "c",
178185
"à": "a"
179186
}
180-
return txt.replace(''.join([*bad_chars.keys()]), ''.join([*bad_chars.values()]))
187+
return txt.replace(''.join([*bad_chars.keys()]), ''.join([*bad_chars.values()]))
188+
189+
def safe_print(txt: str):
190+
"""
191+
Escape the bad characters to avoid ANSI injections.
192+
Also works for Rich printers.
193+
"""
194+
return txt.encode("unicode_escape").decode().replace('[', '\\[')

0 commit comments

Comments
 (0)