mirror of
https://github.com/anotherhadi/github-recon.git
synced 2026-10-05 10:58:25 +02:00
@@ -24,9 +24,9 @@ const (
|
|||||||
func (r Recon) CloseFriends(username string) (response []CloseFriendsResult) {
|
func (r Recon) CloseFriends(username string) (response []CloseFriendsResult) {
|
||||||
r.PrintTitle("🧑🤝🧑 Close Friends")
|
r.PrintTitle("🧑🤝🧑 Close Friends")
|
||||||
|
|
||||||
following, resp, err := r.client.Users.ListFollowing(r.ctx, username, nil)
|
following, resp, err := r.Client.Users.ListFollowing(r.Ctx, username, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to fetch user's following list", "user", username, "err", err)
|
r.Logger.Error("Failed to fetch user's following list", "user", username, "err", err)
|
||||||
r.PrintNewline()
|
r.PrintNewline()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -55,15 +55,15 @@ func (r Recon) CloseFriends(username string) (response []CloseFriendsResult) {
|
|||||||
for _, userBeingFollowedByTarget := range following {
|
for _, userBeingFollowedByTarget := range following {
|
||||||
loginName := userBeingFollowedByTarget.GetLogin()
|
loginName := userBeingFollowedByTarget.GetLogin()
|
||||||
if loginName == "" {
|
if loginName == "" {
|
||||||
r.logger.Warn("User in following list has an empty login", "target_user", username)
|
r.Logger.Warn("User in following list has an empty login", "target_user", username)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
currentScore := 0
|
currentScore := 0
|
||||||
|
|
||||||
userDetails, userResp, userErr := r.client.Users.Get(r.ctx, loginName)
|
userDetails, userResp, userErr := r.Client.Users.Get(r.Ctx, loginName)
|
||||||
if userErr != nil {
|
if userErr != nil {
|
||||||
r.logger.Warn(
|
r.Logger.Warn(
|
||||||
"Failed to fetch details for followed user",
|
"Failed to fetch details for followed user",
|
||||||
"followed_user",
|
"followed_user",
|
||||||
loginName,
|
loginName,
|
||||||
@@ -119,9 +119,9 @@ func (r Recon) CloseFriends(username string) (response []CloseFriendsResult) {
|
|||||||
|
|
||||||
// checkIfUserFollows checks if sourceUserLogin follows targetUserLogin.
|
// checkIfUserFollows checks if sourceUserLogin follows targetUserLogin.
|
||||||
func (r Recon) checkIfUserFollows(sourceUserLogin, targetUserLogin string) (bool, error) {
|
func (r Recon) checkIfUserFollows(sourceUserLogin, targetUserLogin string) (bool, error) {
|
||||||
isFollowing, resp, err := r.client.Users.IsFollowing(r.ctx, sourceUserLogin, targetUserLogin)
|
isFollowing, resp, err := r.Client.Users.IsFollowing(r.Ctx, sourceUserLogin, targetUserLogin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Warn("Error checking if user follows target",
|
r.Logger.Warn("Error checking if user follows target",
|
||||||
"source_user_checking", sourceUserLogin,
|
"source_user_checking", sourceUserLogin,
|
||||||
"target_user_to_check", targetUserLogin,
|
"target_user_to_check", targetUserLogin,
|
||||||
"err", err)
|
"err", err)
|
||||||
|
|||||||
+3
-3
@@ -20,8 +20,8 @@ func (r Recon) Commits(username string) (response []CommitsResult) {
|
|||||||
|
|
||||||
collect := func(date string) error {
|
collect := func(date string) error {
|
||||||
for page := 1; page <= 10; page++ {
|
for page := 1; page <= 10; page++ {
|
||||||
result, resp, err := r.client.Search.Commits(
|
result, resp, err := r.Client.Search.Commits(
|
||||||
r.ctx,
|
r.Ctx,
|
||||||
fmt.Sprintf("author:%s author-date:%s", username, date),
|
fmt.Sprintf("author:%s author-date:%s", username, date),
|
||||||
&github.SearchOptions{
|
&github.SearchOptions{
|
||||||
Sort: "author-date",
|
Sort: "author-date",
|
||||||
@@ -71,7 +71,7 @@ func (r Recon) Commits(username string) (response []CommitsResult) {
|
|||||||
">2026-01-01",
|
">2026-01-01",
|
||||||
} {
|
} {
|
||||||
if err := collect(date); err != nil {
|
if err := collect(date); err != nil {
|
||||||
r.logger.Error("Failed to fetch commits", "err", err, "date", date)
|
r.Logger.Error("Failed to fetch commits", "err", err, "date", date)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -87,15 +87,15 @@ type DeepResult struct {
|
|||||||
|
|
||||||
func (r Recon) Deep(username, excludeRepos string, refresh bool) (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,
|
||||||
username,
|
username,
|
||||||
&github.RepositoryListByUserOptions{
|
&github.RepositoryListByUserOptions{
|
||||||
Type: "all",
|
Type: "all",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to fetch repositories", "err", err)
|
r.Logger.Error("Failed to fetch repositories", "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ func (r Recon) Deep(username, excludeRepos string, refresh bool) (response []Dee
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
maxRepoSize := r.maxRepoSize * 1024
|
maxRepoSize := r.MaxRepoSize * 1024
|
||||||
|
|
||||||
if repo.Size > maxRepoSize {
|
if repo.Size > maxRepoSize {
|
||||||
r.PrintInfo(
|
r.PrintInfo(
|
||||||
@@ -174,7 +174,7 @@ func (r Recon) Deep(username, excludeRepos string, refresh bool) (response []Dee
|
|||||||
)
|
)
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error(
|
r.Logger.Error(
|
||||||
"ERROR",
|
"ERROR",
|
||||||
"Failed to clone repository",
|
"Failed to clone repository",
|
||||||
"err",
|
"err",
|
||||||
@@ -190,7 +190,7 @@ func (r Recon) Deep(username, excludeRepos string, refresh bool) (response []Dee
|
|||||||
r.PrintInfo("INFO", "Now searching for emails in cloned repositories, this may take a while...")
|
r.PrintInfo("INFO", "Now searching for emails in cloned repositories, this may take a while...")
|
||||||
results, err := findEmailsAndOccurrencesInDir(tmp_folder)
|
results, err := findEmailsAndOccurrencesInDir(tmp_folder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to find emails in directory", "err", err)
|
r.Logger.Error("Failed to find emails in directory", "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -21,8 +21,8 @@ func (r Recon) Email(email string) (response []EmailResult) {
|
|||||||
|
|
||||||
collect := func(date string) error {
|
collect := func(date string) error {
|
||||||
for page := 1; page <= 10; page++ {
|
for page := 1; page <= 10; page++ {
|
||||||
result, resp, err := r.client.Search.Commits(
|
result, resp, err := r.Client.Search.Commits(
|
||||||
r.ctx,
|
r.Ctx,
|
||||||
fmt.Sprintf("author-email:%s author-date:%s", email, date),
|
fmt.Sprintf("author-email:%s author-date:%s", email, date),
|
||||||
&github.SearchOptions{
|
&github.SearchOptions{
|
||||||
Sort: "author-date",
|
Sort: "author-date",
|
||||||
@@ -77,7 +77,7 @@ func (r Recon) Email(email string) (response []EmailResult) {
|
|||||||
">2026-01-01",
|
">2026-01-01",
|
||||||
} {
|
} {
|
||||||
if err := collect(date); err != nil {
|
if err := collect(date); err != nil {
|
||||||
r.logger.Error("Failed to fetch commits", "err", err, "date", date)
|
r.Logger.Error("Failed to fetch commits", "err", err, "date", date)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -17,9 +17,9 @@ type SSHKeyResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) SshKeys(username string) (response []SSHKeyResult) {
|
func (r Recon) SshKeys(username string) (response []SSHKeyResult) {
|
||||||
sshKeys, resp, err := r.client.Users.ListKeys(r.ctx, username, nil)
|
sshKeys, resp, err := r.Client.Users.ListKeys(r.Ctx, username, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to fetch ssh keys", "err", err)
|
r.Logger.Error("Failed to fetch ssh keys", "err", err)
|
||||||
} else if len(sshKeys) == 0 {
|
} else if len(sshKeys) == 0 {
|
||||||
r.PrintTitle("🔑 SSH Keys")
|
r.PrintTitle("🔑 SSH Keys")
|
||||||
r.PrintInfo("INFO", "No SSH Keys found")
|
r.PrintInfo("INFO", "No SSH Keys found")
|
||||||
@@ -74,9 +74,9 @@ type GPGKeyResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) GpgKeys(username string) (response []GPGKeyResult) {
|
func (r Recon) GpgKeys(username string) (response []GPGKeyResult) {
|
||||||
gpgKeys, resp, err := r.client.Users.ListGPGKeys(r.ctx, username, nil)
|
gpgKeys, resp, err := r.Client.Users.ListGPGKeys(r.Ctx, username, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to fetch user's gpg keys", "err", err)
|
r.Logger.Error("Failed to fetch user's gpg keys", "err", err)
|
||||||
} else if len(gpgKeys) == 0 {
|
} else if len(gpgKeys) == 0 {
|
||||||
r.PrintTitle("🗝️ GPG Keys")
|
r.PrintTitle("🗝️ GPG Keys")
|
||||||
r.PrintInfo("INFO", "No GPG Keys found")
|
r.PrintInfo("INFO", "No GPG Keys found")
|
||||||
@@ -158,13 +158,13 @@ type SSHSigningKeyResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) SshSigningKeys(username string) (response []SSHSigningKeyResult) {
|
func (r Recon) SshSigningKeys(username string) (response []SSHSigningKeyResult) {
|
||||||
signingKeys, resp, err := r.client.Users.ListSSHSigningKeys(
|
signingKeys, resp, err := r.Client.Users.ListSSHSigningKeys(
|
||||||
r.ctx,
|
r.Ctx,
|
||||||
username,
|
username,
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to fetch user's ssh signing keys", "err", err)
|
r.Logger.Error("Failed to fetch user's ssh signing keys", "err", err)
|
||||||
} else if len(signingKeys) == 0 {
|
} else if len(signingKeys) == 0 {
|
||||||
r.PrintTitle("📝 SSH Signing Keys")
|
r.PrintTitle("📝 SSH Signing Keys")
|
||||||
r.PrintInfo("INFO", "No SSH Signing Keys found")
|
r.PrintInfo("INFO", "No SSH Signing Keys found")
|
||||||
|
|||||||
+12
-12
@@ -8,12 +8,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Recon struct {
|
type Recon struct {
|
||||||
client *github.Client
|
Client *github.Client
|
||||||
logger *log.Logger
|
Logger *log.Logger
|
||||||
ctx context.Context
|
Ctx context.Context
|
||||||
silent bool
|
Silent bool
|
||||||
jsonFile string
|
JsonFile string
|
||||||
maxRepoSize int
|
MaxRepoSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRecon(
|
func NewRecon(
|
||||||
@@ -25,11 +25,11 @@ func NewRecon(
|
|||||||
maxRepoSize int,
|
maxRepoSize int,
|
||||||
) *Recon {
|
) *Recon {
|
||||||
return &Recon{
|
return &Recon{
|
||||||
client: client,
|
Client: client,
|
||||||
logger: logger,
|
Logger: logger,
|
||||||
ctx: ctx,
|
Ctx: ctx,
|
||||||
silent: silent,
|
Silent: silent,
|
||||||
jsonFile: jsonFile,
|
JsonFile: jsonFile,
|
||||||
maxRepoSize: maxRepoSize,
|
MaxRepoSize: maxRepoSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -12,9 +12,9 @@ type OrgResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) Orgs(username string) (response []OrgResult) {
|
func (r Recon) Orgs(username string) (response []OrgResult) {
|
||||||
orgs, resp, err := r.client.Organizations.List(r.ctx, username, nil)
|
orgs, resp, err := r.Client.Organizations.List(r.Ctx, username, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to fetch organizations", "err", err)
|
r.Logger.Error("Failed to fetch organizations", "err", err)
|
||||||
} else if len(orgs) == 0 {
|
} else if len(orgs) == 0 {
|
||||||
r.PrintTitle("🏢 Organizations")
|
r.PrintTitle("🏢 Organizations")
|
||||||
r.PrintInfo("INFO", "No Organizations found")
|
r.PrintInfo("INFO", "No Organizations found")
|
||||||
|
|||||||
+3
-3
@@ -11,16 +11,16 @@ type SocialResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) Socials(username string) (response []SocialResult) {
|
func (r Recon) Socials(username string) (response []SocialResult) {
|
||||||
resp, err := FetchGitHubAPI(r.client, "", "/users/"+username+"/social_accounts")
|
resp, err := FetchGitHubAPI(r.Client, "", "/users/"+username+"/social_accounts")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to fetch socials", "err", err)
|
r.Logger.Error("Failed to fetch socials", "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var socialAccounts []SocialResult
|
var socialAccounts []SocialResult
|
||||||
err = json.Unmarshal(resp, &socialAccounts)
|
err = json.Unmarshal(resp, &socialAccounts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to unmarshal socials", "err", err)
|
r.Logger.Error("Failed to unmarshal socials", "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -30,12 +30,12 @@ type UserResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) User(username string) (response UserResult) {
|
func (r Recon) User(username string) (response UserResult) {
|
||||||
user, resp, err := r.client.Users.Get(r.ctx, username)
|
user, resp, err := r.Client.Users.Get(r.Ctx, username)
|
||||||
if resp.StatusCode == 404 {
|
if resp.StatusCode == 404 {
|
||||||
r.logger.Fatal("User not found")
|
r.Logger.Fatal("User not found")
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Fatal("Failed to fetch user's information", "err", err)
|
r.Logger.Fatal("Failed to fetch user's information", "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.PrintTitle("👤 User informations")
|
r.PrintTitle("👤 User informations")
|
||||||
|
|||||||
+9
-9
@@ -25,7 +25,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (r Recon) Header() {
|
func (r Recon) Header() {
|
||||||
if r.silent {
|
if r.Silent {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
asciiArt := " __ \n ___ _/ / _______ _______ ___ \n / _ `/ _ \\/ __/ -_) __/ _ \\/ _ \\\n \\_, /_//_/_/ \\__/\\__/\\___/_//_/\n/___/ "
|
asciiArt := " __ \n ___ _/ / _______ _______ ___ \n / _ `/ _ \\/ __/ -_) __/ _ \\/ _ \\\n \\_, /_//_/_/ \\__/\\__/\\___/_//_/\n/___/ "
|
||||||
@@ -91,14 +91,14 @@ func FetchGitHubAPI(github *github.Client, token, path string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) PrintNewline() {
|
func (r Recon) PrintNewline() {
|
||||||
if r.silent {
|
if r.Silent {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) PrintTitle(title string) {
|
func (r Recon) PrintTitle(title string) {
|
||||||
if r.silent {
|
if r.Silent {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
style := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#7287fd"))
|
style := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#7287fd"))
|
||||||
@@ -106,7 +106,7 @@ func (r Recon) PrintTitle(title string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) PrintInfo(key, value string, more ...string) {
|
func (r Recon) PrintInfo(key, value string, more ...string) {
|
||||||
if r.silent {
|
if r.Silent {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if value == "" || value == "0001-01-01 00:00:00 +0000 UTC" {
|
if value == "" || value == "0001-01-01 00:00:00 +0000 UTC" {
|
||||||
@@ -144,20 +144,20 @@ func SkipResult(name, email string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r Recon) WriteJson(data any) {
|
func (r Recon) WriteJson(data any) {
|
||||||
if r.jsonFile == "" {
|
if r.JsonFile == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
file, err := os.Create(r.jsonFile)
|
file, err := os.Create(r.JsonFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to create JSON file", "err", err)
|
r.Logger.Error("Failed to create JSON file", "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
as_json, _ := json.MarshalIndent(data, "", "\t")
|
as_json, _ := json.MarshalIndent(data, "", "\t")
|
||||||
_, err = file.Write(as_json)
|
_, err = file.Write(as_json)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to write to JSON file", "err", err)
|
r.Logger.Error("Failed to write to JSON file", "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.PrintInfo("INFO", "JSON file created successfully", "file", r.jsonFile)
|
r.PrintInfo("INFO", "JSON file created successfully", "file", r.JsonFile)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user