mirror of
https://github.com/anotherhadi/github-recon.git
synced 2026-10-05 10:58:25 +02:00
+31
-1
@@ -82,9 +82,10 @@ type DeepResult struct {
|
|||||||
Repository string
|
Repository string
|
||||||
Owner string
|
Owner string
|
||||||
Name string
|
Name string
|
||||||
|
Size int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) Deep(username, excludeRepos string) (response []DeepResult) {
|
func (r Recon) Deep(username, excludeRepos string, refresh bool) (response []DeepResult) {
|
||||||
excludeReposList := strings.Split(excludeRepos, ",")
|
excludeReposList := strings.Split(excludeRepos, ",")
|
||||||
repos, resp, err := r.client.Repositories.ListByUser(
|
repos, resp, err := r.client.Repositories.ListByUser(
|
||||||
r.ctx,
|
r.ctx,
|
||||||
@@ -107,6 +108,7 @@ func (r Recon) Deep(username, excludeRepos string) (response []DeepResult) {
|
|||||||
Repository: repo.GetCloneURL(),
|
Repository: repo.GetCloneURL(),
|
||||||
Owner: repo.GetOwner().GetLogin(),
|
Owner: repo.GetOwner().GetLogin(),
|
||||||
Name: repo.GetName(),
|
Name: repo.GetName(),
|
||||||
|
Size: repo.GetSize(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,15 +121,43 @@ func (r Recon) Deep(username, excludeRepos string) (response []DeepResult) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tmp_folder := "/tmp/ghrecon-" + username
|
tmp_folder := "/tmp/ghrecon-" + username
|
||||||
|
|
||||||
|
if folderExists(tmp_folder) {
|
||||||
|
if refresh {
|
||||||
|
r.PrintInfo("INFO", "Deleting existing folder "+tmp_folder)
|
||||||
|
err := os.RemoveAll(tmp_folder)
|
||||||
|
if err != nil {
|
||||||
|
r.PrintInfo("ERROR", "Failed to delete existing folder "+tmp_folder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, repo := range response {
|
for _, repo := range response {
|
||||||
if slices.Contains(excludeReposList, repo.Name) ||
|
if slices.Contains(excludeReposList, repo.Name) ||
|
||||||
slices.Contains(excludeReposList, repo.Owner+"/"+repo.Name) {
|
slices.Contains(excludeReposList, repo.Owner+"/"+repo.Name) {
|
||||||
r.PrintInfo("INFO", "Skipping repository", repo.Owner+"/"+repo.Name)
|
r.PrintInfo("INFO", "Skipping repository", repo.Owner+"/"+repo.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxRepoSize := r.maxRepoSize * 1024
|
||||||
|
|
||||||
|
if repo.Size > maxRepoSize {
|
||||||
|
r.PrintInfo(
|
||||||
|
"INFO",
|
||||||
|
"Skipping repository "+repo.Owner+"/"+repo.Name+" due to size", fmt.Sprintf(
|
||||||
|
"%d",
|
||||||
|
repo.Size/1024,
|
||||||
|
)+"MB > "+fmt.Sprintf(
|
||||||
|
"%d",
|
||||||
|
maxRepoSize/1024,
|
||||||
|
)+"MB",
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
r.PrintInfo(
|
r.PrintInfo(
|
||||||
"Downloading",
|
"Downloading",
|
||||||
repo.Owner+"/"+repo.Name,
|
repo.Owner+"/"+repo.Name,
|
||||||
|
fmt.Sprintf("%d", repo.Size/1024)+"MB",
|
||||||
)
|
)
|
||||||
|
|
||||||
destination := tmp_folder + "/" + repo.Owner + "/" + repo.Name
|
destination := tmp_folder + "/" + repo.Owner + "/" + repo.Name
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ type Recon struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
silent bool
|
silent bool
|
||||||
jsonFile string
|
jsonFile string
|
||||||
|
maxRepoSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRecon(
|
func NewRecon(
|
||||||
@@ -21,6 +22,7 @@ func NewRecon(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
silent bool,
|
silent bool,
|
||||||
jsonFile string,
|
jsonFile string,
|
||||||
|
maxRepoSize int,
|
||||||
) *Recon {
|
) *Recon {
|
||||||
return &Recon{
|
return &Recon{
|
||||||
client: client,
|
client: client,
|
||||||
@@ -28,5 +30,6 @@ func NewRecon(
|
|||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
silent: silent,
|
silent: silent,
|
||||||
jsonFile: jsonFile,
|
jsonFile: jsonFile,
|
||||||
|
maxRepoSize: maxRepoSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,17 @@ func main() {
|
|||||||
var silent bool
|
var silent bool
|
||||||
var jsonFile string
|
var jsonFile string
|
||||||
var excludeRepos string
|
var excludeRepos string
|
||||||
|
var maxRepoSize int
|
||||||
|
var refresh bool
|
||||||
flag.StringVarP(&username, "username", "u", "", "GitHub username to analyze")
|
flag.StringVarP(&username, "username", "u", "", "GitHub username to analyze")
|
||||||
flag.StringVarP(&token, "token", "t", "", "GitHub personal access token (e.g. ghp_...)")
|
flag.StringVarP(&token, "token", "t", "", "GitHub personal access token (e.g. ghp_...)")
|
||||||
flag.StringVarP(&fromEmail, "email", "e", "", "Search accounts by email address")
|
flag.StringVarP(&fromEmail, "email", "e", "", "Search accounts by email address")
|
||||||
|
flag.IntVar(
|
||||||
|
&maxRepoSize,
|
||||||
|
"max-size",
|
||||||
|
150,
|
||||||
|
"Limit the size of repositories to scan (in MB) (Only for deep scan)",
|
||||||
|
)
|
||||||
flag.BoolVarP(
|
flag.BoolVarP(
|
||||||
&onlyCommitsLeak,
|
&onlyCommitsLeak,
|
||||||
"only-commits",
|
"only-commits",
|
||||||
@@ -29,6 +37,13 @@ func main() {
|
|||||||
false,
|
false,
|
||||||
"Display only commits with author info",
|
"Display only commits with author info",
|
||||||
)
|
)
|
||||||
|
flag.BoolVarP(
|
||||||
|
&refresh,
|
||||||
|
"refresh",
|
||||||
|
"r",
|
||||||
|
false,
|
||||||
|
"Refresh the cache (deep scan only)",
|
||||||
|
)
|
||||||
flag.BoolVarP(
|
flag.BoolVarP(
|
||||||
&deep,
|
&deep,
|
||||||
"deep",
|
"deep",
|
||||||
@@ -85,6 +100,7 @@ func main() {
|
|||||||
ctx,
|
ctx,
|
||||||
silent,
|
silent,
|
||||||
jsonFile,
|
jsonFile,
|
||||||
|
maxRepoSize,
|
||||||
)
|
)
|
||||||
|
|
||||||
r.Header()
|
r.Header()
|
||||||
@@ -130,7 +146,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if deep {
|
if deep {
|
||||||
results["Deep"] = r.Deep(username, excludeRepos)
|
results["Deep"] = r.Deep(username, excludeRepos, refresh)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.WriteJson(results)
|
r.WriteJson(results)
|
||||||
|
|||||||
Reference in New Issue
Block a user