mirror of
https://github.com/anotherhadi/github-recon.git
synced 2026-10-05 19:08:24 +02:00
+60
-39
@@ -6,66 +6,87 @@ import (
|
||||
"github.com/google/go-github/v72/github"
|
||||
)
|
||||
|
||||
func (r Recon) Commits(username string) {
|
||||
PrintTitle("🐙 Commits")
|
||||
type CommitsResult struct {
|
||||
Name string
|
||||
Email string
|
||||
Occurences int
|
||||
FirstFoundIn string
|
||||
}
|
||||
|
||||
seenNames := make(map[string]struct{})
|
||||
seenEmails := make(map[string]struct{})
|
||||
var names, emails []string
|
||||
func (r Recon) Commits(username string) (response []CommitsResult) {
|
||||
r.PrintTitle("🐙 Commits")
|
||||
|
||||
collect := func(order string) error {
|
||||
opts := &github.SearchOptions{
|
||||
Sort: "author-date",
|
||||
Order: order,
|
||||
ListOptions: github.ListOptions{PerPage: 100},
|
||||
}
|
||||
results := make(map[string]CommitsResult)
|
||||
|
||||
collect := func(date string) error {
|
||||
for page := 1; page <= 10; page++ {
|
||||
opts.ListOptions.Page = page
|
||||
result, resp, err := r.client.Search.Commits(
|
||||
r.ctx,
|
||||
fmt.Sprintf("author:%s", username),
|
||||
opts,
|
||||
fmt.Sprintf("author:%s author-date:%s", username, date),
|
||||
&github.SearchOptions{
|
||||
Sort: "author-date",
|
||||
Order: "desc",
|
||||
ListOptions: github.ListOptions{PerPage: 100, Page: page},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fetch page %d (%s): %w", page, order, err)
|
||||
return fmt.Errorf("fetch page %d (%s): %w", page, date, err)
|
||||
}
|
||||
WaitForRateLimit(resp)
|
||||
if len(result.Commits) == 0 {
|
||||
break
|
||||
}
|
||||
for _, item := range result.Commits {
|
||||
a := item.Commit.GetAuthor()
|
||||
name := a.GetName()
|
||||
email := a.GetEmail()
|
||||
if _, seen := seenNames[name]; !seen {
|
||||
seenNames[name] = struct{}{}
|
||||
names = append(names, name)
|
||||
PrintInfo(
|
||||
"Name "+fmt.Sprint(len(names)),
|
||||
name,
|
||||
"from "+item.GetRepository().Owner.GetLogin()+"/"+item.GetRepository().
|
||||
GetName(),
|
||||
)
|
||||
name := item.Commit.GetAuthor().GetName()
|
||||
email := item.Commit.GetAuthor().GetEmail()
|
||||
if SkipResult(name, email) {
|
||||
// continue
|
||||
}
|
||||
if _, seen := seenEmails[email]; !seen {
|
||||
seenEmails[email] = struct{}{}
|
||||
emails = append(emails, email)
|
||||
PrintInfo(
|
||||
"Email "+fmt.Sprint(len(emails)),
|
||||
email,
|
||||
"from "+item.GetRepository().Owner.GetLogin()+"/"+item.GetRepository().
|
||||
if _, seen := results[name+" - "+email]; !seen {
|
||||
author := CommitsResult{
|
||||
Name: name,
|
||||
Email: email,
|
||||
Occurences: 1,
|
||||
FirstFoundIn: item.GetRepository().Owner.GetLogin() + "/" + item.GetRepository().
|
||||
GetName(),
|
||||
)
|
||||
}
|
||||
results[name+" - "+email] = author
|
||||
} else {
|
||||
result := results[name+" - "+email]
|
||||
result.Occurences++
|
||||
results[name+" - "+email] = result
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := collect("desc"); err != nil {
|
||||
r.logger.Error("Failed to fetch commits", "err", err, "order", "desc")
|
||||
// Range of dates to bypass the limit of 1000 results
|
||||
for _, date := range []string{
|
||||
"<2023-01-01", "2023-01-01..2023-12-31",
|
||||
"2024-01-01..2024-05-31",
|
||||
"2024-06-01..2024-12-31",
|
||||
"2025-01-01..2025-05-31",
|
||||
"2025-06-01..2025-12-31",
|
||||
">2026-01-01",
|
||||
} {
|
||||
if err := collect(date); err != nil {
|
||||
r.logger.Error("Failed to fetch commits", "err", err, "date", date)
|
||||
}
|
||||
}
|
||||
if err := collect("asc"); err != nil {
|
||||
r.logger.Error("Failed to fetch commits", "err", err, "order", "asc")
|
||||
|
||||
for _, result := range results {
|
||||
r.PrintInfo(
|
||||
"Author",
|
||||
result.Name+" - "+result.Email,
|
||||
"first from "+result.FirstFoundIn+" (x"+fmt.Sprint(result.Occurences)+")",
|
||||
)
|
||||
response = append(response, result)
|
||||
}
|
||||
if len(results) == 0 {
|
||||
r.PrintInfo("INFO", "No commits found")
|
||||
}
|
||||
r.PrintNewline()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user