Compare commits

..
12 Commits
Author SHA1 Message Date
Hadi c163fb4ecd Fatal only in cmd
Signed-off-by: Hadi <[email protected]>
2025-09-17 21:26:54 +02:00
Hadi 325397dfef Check repositories length
Signed-off-by: Hadi <[email protected]>
2025-09-17 21:10:35 +02:00
Hadi dab0ba2b38 now retrying to get commits
Signed-off-by: Hadi <[email protected]>
2025-09-17 21:07:16 +02:00
Hadi 98769561c3 Add author.email in levenshtein distance for authors
Signed-off-by: Hadi <[email protected]>
2025-09-17 20:47:12 +02:00
Hadi c76953882c Nil when no result & better error handling
Signed-off-by: Hadi <[email protected]>
2025-09-17 20:39:53 +02:00
Hadi 94fd83ecce fix print with private interface
Signed-off-by: Hadi <[email protected]>
2025-09-17 20:26:31 +02:00
Hadi 2d01c1639f Fix isDir condition
Signed-off-by: Hadi <[email protected]>
2025-09-17 19:47:50 +02:00
Hadi 66030c1c16 add details to close friends
Signed-off-by: Hadi <[email protected]>
2025-09-17 19:31:54 +02:00
Hadi bb8f34055d fix nixos installation step
Signed-off-by: Hadi <[email protected]>
2025-09-16 19:35:38 +02:00
Hadi 26a1cfdd37 Change the way token is retrieve
Signed-off-by: Hadi <[email protected]>
2025-09-15 14:54:51 +02:00
Hadi 3064cdbf7a Change/get defaults
Signed-off-by: Hadi <[email protected]>
2025-09-15 14:40:55 +02:00
Hadi 52f9f1f3e7 Change settings
Signed-off-by: Hadi <[email protected]>
2025-09-15 14:37:21 +02:00
11 changed files with 142 additions and 71 deletions
+2 -2
View File
@@ -98,7 +98,7 @@ nix run github:anotherhadi/github-recon -- [--flags value] target_username_or_em
# then add it to your packages # then add it to your packages
environment.systemPackages = with pkgs; [ # or home.packages environment.systemPackages = with pkgs; [ # or home.packages
github-recon inputs.github-recon.defaultPackage.${pkgs.system}
]; ];
``` ```
@@ -123,7 +123,7 @@ github-recon [--flags value] target_username_or_email
--trufflehog Run trufflehog on cloned repositories (only for deep scan) (default true) --trufflehog Run trufflehog on cloned repositories (only for deep scan) (default true)
-S, --silent Suppress all non-essential output -S, --silent Suppress all non-essential output
--spoof-email Spoof email (only for email mode) (default true) --spoof-email Spoof email (only for email mode) (default true)
-a, --hide-avatar Hide the avatar in the output -a, --print-avatar Show the avatar in the output
-j, --json string Write results to specified JSON file -j, --json string Write results to specified JSON file
``` ```
+10 -2
View File
@@ -1,6 +1,8 @@
package main package main
import ( import (
"log"
recon_email "github.com/anotherhadi/github-recon/github-recon/email" recon_email "github.com/anotherhadi/github-recon/github-recon/email"
recon_username "github.com/anotherhadi/github-recon/github-recon/username" recon_username "github.com/anotherhadi/github-recon/github-recon/username"
github_recon_settings "github.com/anotherhadi/github-recon/settings" github_recon_settings "github.com/anotherhadi/github-recon/settings"
@@ -8,7 +10,10 @@ import (
) )
func main() { func main() {
settings := github_recon_settings.GetSettings() settings, err := github_recon_settings.GetSettings()
if err != nil {
log.Fatal(err)
}
if !settings.Silent { if !settings.Silent {
utils.Header() utils.Header()
@@ -23,7 +28,10 @@ func main() {
} }
if settings.TargetType == github_recon_settings.TargetUsername { if settings.TargetType == github_recon_settings.TargetUsername {
result := recon_username.Username(settings) result, err := recon_username.Username(settings)
if err != nil {
log.Fatal(err)
}
writeJson(settings, result) writeJson(settings, result)
} else { } else {
result := recon_email.Email(settings) result := recon_email.Email(settings)
+2 -2
View File
@@ -13,7 +13,7 @@ type EmailResult struct {
TargetType github_recon_settings.TargetType TargetType github_recon_settings.TargetType
Commits CommitsResult Commits CommitsResult
Spoofing SpoofingResult Spoofing *SpoofingResult
} }
func Email(settings github_recon_settings.Settings) EmailResult { func Email(settings github_recon_settings.Settings) EmailResult {
@@ -33,7 +33,7 @@ func Email(settings github_recon_settings.Settings) EmailResult {
} else { } else {
utils.PrintTitle(settings.Silent, "🎭 Spoofing test") utils.PrintTitle(settings.Silent, "🎭 Spoofing test")
result.Spoofing = Spoofing(settings) result.Spoofing = Spoofing(settings)
if result.Spoofing.AvatarURL != "" { if result.Spoofing != nil && result.Spoofing.AvatarURL != "" {
utils.PrintAvatar(settings, result.Spoofing.AvatarURL) utils.PrintAvatar(settings, result.Spoofing.AvatarURL)
} }
utils.PrintStruct(settings, result.Spoofing, 0) utils.PrintStruct(settings, result.Spoofing, 0)
+20 -10
View File
@@ -2,6 +2,7 @@ package recon
import ( import (
"math/rand" "math/rand"
"time"
github_recon_settings "github.com/anotherhadi/github-recon/settings" github_recon_settings "github.com/anotherhadi/github-recon/settings"
"github.com/anotherhadi/github-recon/utils" "github.com/anotherhadi/github-recon/utils"
@@ -26,7 +27,8 @@ func RandomString(n int) string {
return string(b) return string(b)
} }
func Spoofing(s github_recon_settings.Settings) (response SpoofingResult) { func Spoofing(s github_recon_settings.Settings) (response *SpoofingResult) {
response = &SpoofingResult{}
name := "gh-recon-spoofing-" + RandomString(8) name := "gh-recon-spoofing-" + RandomString(8)
private := true private := true
autoInit := true autoInit := true
@@ -41,6 +43,13 @@ func Spoofing(s github_recon_settings.Settings) (response SpoofingResult) {
} }
utils.WaitForRateLimit(s, resp) utils.WaitForRateLimit(s, resp)
defer func() {
_, err = s.Client.Repositories.Delete(s.Ctx, repo.Owner.GetLogin(), name)
if err != nil {
s.Logger.Error("Error while deleting repo", "err", err)
}
}()
branch := repo.GetDefaultBranch() branch := repo.GetDefaultBranch()
if branch == "" { if branch == "" {
branch = "main" branch = "main"
@@ -57,7 +66,6 @@ func Spoofing(s github_recon_settings.Settings) (response SpoofingResult) {
ref, resp, err := s.Client.Git.GetRef(s.Ctx, repo.Owner.GetLogin(), name, refName) ref, resp, err := s.Client.Git.GetRef(s.Ctx, repo.Owner.GetLogin(), name, refName)
if err != nil { if err != nil {
s.Logger.Error("Error while getting ref", "err", err) s.Logger.Error("Error while getting ref", "err", err)
s.Logger.Warn("The temp repo was left undeleted", "repo", repo.GetHTMLURL())
return return
} }
utils.WaitForRateLimit(s, resp) utils.WaitForRateLimit(s, resp)
@@ -65,7 +73,6 @@ func Spoofing(s github_recon_settings.Settings) (response SpoofingResult) {
parentCommit, resp, err := s.Client.Git.GetCommit(s.Ctx, repo.Owner.GetLogin(), name, ref.GetObject().GetSHA()) parentCommit, resp, err := s.Client.Git.GetCommit(s.Ctx, repo.Owner.GetLogin(), name, ref.GetObject().GetSHA())
if err != nil { if err != nil {
s.Logger.Error("Error while getting parent commit", "err", err) s.Logger.Error("Error while getting parent commit", "err", err)
s.Logger.Warn("The temp repo was left undeleted", "repo", repo.GetHTMLURL())
return return
} }
utils.WaitForRateLimit(s, resp) utils.WaitForRateLimit(s, resp)
@@ -81,7 +88,6 @@ func Spoofing(s github_recon_settings.Settings) (response SpoofingResult) {
newCommit, resp, err := s.Client.Git.CreateCommit(s.Ctx, repo.Owner.GetLogin(), name, commit, nil) newCommit, resp, err := s.Client.Git.CreateCommit(s.Ctx, repo.Owner.GetLogin(), name, commit, nil)
if err != nil { if err != nil {
s.Logger.Error("Error while creating spoofed empty commit", "err", err) s.Logger.Error("Error while creating spoofed empty commit", "err", err)
s.Logger.Warn("The temp repo was left undeleted", "repo", repo.GetHTMLURL())
return return
} }
utils.WaitForRateLimit(s, resp) utils.WaitForRateLimit(s, resp)
@@ -90,31 +96,35 @@ func Spoofing(s github_recon_settings.Settings) (response SpoofingResult) {
_, resp, err = s.Client.Git.UpdateRef(s.Ctx, repo.Owner.GetLogin(), name, ref, false) _, resp, err = s.Client.Git.UpdateRef(s.Ctx, repo.Owner.GetLogin(), name, ref, false)
if err != nil { if err != nil {
s.Logger.Error("Error while updating ref to spoofed commit", "err", err) s.Logger.Error("Error while updating ref to spoofed commit", "err", err)
s.Logger.Warn("The temp repo was left undeleted", "repo", repo.GetHTMLURL())
return return
} }
utils.WaitForRateLimit(s, resp) utils.WaitForRateLimit(s, resp)
const maxRetries = 5
const retryDelay = 2 * time.Second
for i := 0; i < maxRetries; i++ {
commits, _, err := s.Client.Repositories.ListCommits(s.Ctx, repo.Owner.GetLogin(), name, nil) commits, _, err := s.Client.Repositories.ListCommits(s.Ctx, repo.Owner.GetLogin(), name, nil)
if err != nil { if err != nil {
s.Logger.Error("Error while listing commits", "err", err) s.Logger.Error("Error while listing commits", "err", err)
s.Logger.Warn("The temp repo was left undeleted", "repo", repo.GetHTMLURL())
return return
} }
if len(commits) > 0 { if len(commits) > 1 {
last := commits[0] last := commits[0]
response.Username = last.GetAuthor().GetLogin() response.Username = last.GetAuthor().GetLogin()
response.Name = last.GetAuthor().GetName() response.Name = last.GetAuthor().GetName()
response.Email = last.GetAuthor().GetEmail() response.Email = last.GetAuthor().GetEmail()
response.Url = last.GetAuthor().GetHTMLURL() response.Url = last.GetAuthor().GetHTMLURL()
response.AvatarURL = last.GetAuthor().GetAvatarURL() response.AvatarURL = last.GetAuthor().GetAvatarURL()
break
} }
_, err = s.Client.Repositories.Delete(s.Ctx, repo.Owner.GetLogin(), name) s.Logger.Info("Only one commit found, retrying...", "attempt", i+1)
if err != nil { time.Sleep(retryDelay)
s.Logger.Error("Error while deleting repo", "err", err)
} }
if response.Username == "" && response.Name == "" && response.Email == "" {
return nil
}
return return
} }
+17
View File
@@ -13,7 +13,11 @@ import (
type CloseFriendsResult []CloseFriendResult type CloseFriendsResult []CloseFriendResult
type CloseFriendResult struct { type CloseFriendResult struct {
Name string
Username string Username string
Orgs []string
Company string
Location string
Score int Score int
} }
@@ -96,8 +100,12 @@ func CloseFriends(s github_recon_settings.Settings) (results CloseFriendsResult)
// Add candidate if they matched at least one condition // Add candidate if they matched at least one condition
if score > 0 { if score > 0 {
results = append(results, CloseFriendResult{ results = append(results, CloseFriendResult{
Name: candidateDetails.GetName(),
Username: candidateLogin, Username: candidateLogin,
Orgs: candidateOrgsToNames(candidateOrgs),
Score: score, Score: score,
Location: candidateDetails.GetLocation(),
Company: candidateDetails.GetCompany(),
}) })
} }
} }
@@ -130,6 +138,15 @@ func checkIfUserFollows(s github_recon_settings.Settings, sourceUser, targetUser
} }
return isFollowing, nil return isFollowing, nil
} }
func candidateOrgsToNames(orgs []*github.Organization) []string {
var orgNames []string
for _, org := range orgs {
if org.GetLogin() != "" {
orgNames = append(orgNames, org.GetLogin())
}
}
return orgNames
}
func getOrgs(s github_recon_settings.Settings, user string) ([]*github.Organization, error) { func getOrgs(s github_recon_settings.Settings, user string) ([]*github.Organization, error) {
orgs, resp, err := s.Client.Organizations.List(s.Ctx, user, nil) orgs, resp, err := s.Client.Organizations.List(s.Ctx, user, nil)
+15 -3
View File
@@ -139,6 +139,11 @@ func DeepScan(s github_recon_settings.Settings) (response DeepScanResult) {
} }
s.Logger.Info("Cloned all repositories", "path", tmp_folder) s.Logger.Info("Cloned all repositories", "path", tmp_folder)
if len(repositories) == 0 {
s.Logger.Info("No repositories found for the user, skipping deep scan.")
return
}
authorOccurrences := Authors{} authorOccurrences := Authors{}
mapAuthorToIndex := make(map[string]int) mapAuthorToIndex := make(map[string]int)
for _, repo := range repositories { for _, repo := range repositories {
@@ -202,7 +207,7 @@ func DeepScan(s github_recon_settings.Settings) (response DeepScanResult) {
Name: authorName, Name: authorName,
Email: authorEmail, Email: authorEmail,
FoundIn: []string{repoIdentifier}, FoundIn: []string{repoIdentifier},
Levenshtein: utils.LevenshteinDistance(s.Target, authorName), Levenshtein: levenshteinDistanceAuthor(s.Target, authorName, authorEmail),
}) })
mapAuthorToIndex[trimmedLine] = len(authorOccurrences) - 1 mapAuthorToIndex[trimmedLine] = len(authorOccurrences) - 1
} }
@@ -334,13 +339,13 @@ func findEmailsAndOccurrencesInDir(rootPath string, username string) (Emails, er
if err != nil { if err != nil {
return err return err
} }
if !d.IsDir() { if d.Type().IsRegular() {
if strings.Contains(path, ".git/logs/") { if strings.Contains(path, ".git/logs/") {
return nil return nil
} }
content, err := os.ReadFile(path) content, err := os.ReadFile(path)
if err != nil { if err != nil {
return err return nil
} }
currentFileEmails := emailRegex.FindAllString(string(content), -1) currentFileEmails := emailRegex.FindAllString(string(content), -1)
@@ -380,3 +385,10 @@ func findEmailsAndOccurrencesInDir(rootPath string, username string) (Emails, er
return results, nil return results, nil
} }
func levenshteinDistanceAuthor(target, name, email string) int {
if strings.Contains(email, "@") {
email = strings.SplitN(email, "@", 2)[0]
}
return slices.Min([]int{utils.LevenshteinDistance(target, name), utils.LevenshteinDistance(target, email)})
}
+7 -5
View File
@@ -27,16 +27,18 @@ type UsernameResult struct {
DeepScan DeepScanResult DeepScan DeepScanResult
} }
func Username(settings github_recon_settings.Settings) UsernameResult { func Username(settings github_recon_settings.Settings) (result UsernameResult, err error) {
result = UsernameResult{
result := UsernameResult{
Target: settings.Target, Target: settings.Target,
TargetType: settings.TargetType, TargetType: settings.TargetType,
DateTime: time.Now().String(), DateTime: time.Now().String(),
} }
utils.PrintTitle(settings.Silent, "👤 User informations") utils.PrintTitle(settings.Silent, "👤 User informations")
result.User = User(settings) result.User, err = User(settings)
if err != nil {
return
}
utils.PrintAvatar(settings, result.User.AvatarURL) utils.PrintAvatar(settings, result.User.AvatarURL)
utils.PrintStruct(settings, result.User, 0) utils.PrintStruct(settings, result.User, 0)
@@ -74,5 +76,5 @@ func Username(settings github_recon_settings.Settings) UsernameResult {
utils.PrintStruct(settings, result.DeepScan, 0) utils.PrintStruct(settings, result.DeepScan, 0)
} }
return result return
} }
+4 -4
View File
@@ -31,13 +31,13 @@ type UserResult struct {
Plan string Plan string
} }
func User(s github_recon_settings.Settings) (response UserResult) { func User(s github_recon_settings.Settings) (response UserResult, err error) {
user, resp, err := s.Client.Users.Get(s.Ctx, s.Target) user, resp, err := s.Client.Users.Get(s.Ctx, s.Target)
if resp.StatusCode == 404 { if resp.StatusCode == 404 {
s.Logger.Fatal("User not found with username") return UserResult{}, fmt.Errorf("user not found with username: %s", s.Target)
} }
if err != nil { if err != nil {
s.Logger.Fatal("Failed to fetch user's information", "err", err) return UserResult{}, fmt.Errorf("failed to fetch user's information")
} }
u := UserResult{ u := UserResult{
@@ -65,5 +65,5 @@ func User(s github_recon_settings.Settings) (response UserResult) {
} }
utils.WaitForRateLimit(s, resp) utils.WaitForRateLimit(s, resp)
return u return u, nil
} }
+46 -27
View File
@@ -32,7 +32,7 @@ type Settings struct {
Silent bool Silent bool
DeepScan bool DeepScan bool
MaxDistance int MaxDistance int
HideAvatar bool PrintAvatar bool
SpoofEmail bool SpoofEmail bool
Trufflehog bool Trufflehog bool
@@ -42,7 +42,34 @@ type Settings struct {
Ctx context.Context Ctx context.Context
} }
func GetSettings() (settings Settings) { func GetDefaultSettings() Settings {
return Settings{
Token: "null",
Target: "",
TargetType: TargetUsername,
ShowSource: false,
Refresh: false,
MaxRepoSize: 150,
ExcludedRepos: []string{},
JsonOutput: "",
Silent: false,
DeepScan: false,
MaxDistance: 20,
PrintAvatar: true,
SpoofEmail: true,
Trufflehog: true,
Client: github.NewClient(nil),
Logger: log.NewWithOptions(os.Stderr, log.Options{
ReportCaller: false,
ReportTimestamp: false,
}),
Ctx: context.WithValue(context.Background(), github.SleepUntilPrimaryRateLimitResetWhenRateLimited, true),
}
}
func GetSettings() (settings Settings, err error) {
settings = GetDefaultSettings()
//// Flag settings //// Flag settings
flag.Usage = func() { flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
@@ -56,74 +83,66 @@ func GetSettings() (settings Settings) {
flag.CommandLine.SortFlags = false flag.CommandLine.SortFlags = false
//// Flags //// Flags
flag.StringVarP(&settings.Token, "token", "t", "null", "Github personal access token (e.g. ghp_aaa...). Can also be set via GITHUB_RECON_TOKEN environment variable. You also need to set the token in $HOME/.config/github-recon/env file if you want to use this tool without passing the token every time.") flag.StringVarP(&settings.Token, "token", "t", settings.Token, "Github personal access token (e.g. ghp_aaa...). Can also be set via GITHUB_RECON_TOKEN environment variable. You also need to set the token in $HOME/.config/github-recon/env file if you want to use this tool without passing the token every time.")
// DeepScan // DeepScan
flag.BoolVarP(&settings.DeepScan, "deepscan", "d", false, "Enable deep scan (clone repos, regex search, analyse licenses, etc.)") flag.BoolVarP(&settings.DeepScan, "deepscan", "d", settings.DeepScan, "Enable deep scan (clone repos, regex search, analyse licenses, etc.)")
flag.IntVar( flag.IntVar(
&settings.MaxRepoSize, &settings.MaxRepoSize,
"max-size", "max-size",
150, settings.MaxRepoSize,
"Limit the size of repositories to scan (in MB) (only for deep scan)", "Limit the size of repositories to scan (in MB) (only for deep scan)",
) )
flag.StringSliceVarP( flag.StringSliceVarP(
&settings.ExcludedRepos, &settings.ExcludedRepos,
"exclude-repo", "exclude-repo",
"e", "e",
[]string{}, settings.ExcludedRepos,
"Exclude repos from deep scan (comma-separated list, only for deep scan)", "Exclude repos from deep scan (comma-separated list, only for deep scan)",
) )
flag.BoolVarP( flag.BoolVarP(
&settings.Refresh, &settings.Refresh,
"refresh", "refresh",
"r", "r",
false, settings.Refresh,
"Refresh the cache (only for deep scan)", "Refresh the cache (only for deep scan)",
) )
flag.BoolVarP( flag.BoolVarP(
&settings.ShowSource, &settings.ShowSource,
"show-source", "show-source",
"s", "s",
false, settings.ShowSource,
"Show where the information (authors, emails, etc) were found (only for deep scan)", "Show where the information (authors, emails, etc) were found (only for deep scan)",
) )
flag.IntVarP( flag.IntVarP(
&settings.MaxDistance, &settings.MaxDistance,
"max-distance", "max-distance",
"m", "m",
20, settings.MaxDistance,
"Maximum Levenshtein distance for matching usernames & emails (only for deep scan)", "Maximum Levenshtein distance for matching usernames & emails (only for deep scan)",
) )
flag.BoolVar( flag.BoolVar(
&settings.Trufflehog, &settings.Trufflehog,
"trufflehog", "trufflehog",
true, settings.Trufflehog,
"Run trufflehog on cloned repositories (only for deep scan)", "Run trufflehog on cloned repositories (only for deep scan)",
) )
flag.BoolVarP(&settings.Silent, "silent", "S", false, "Suppress all non-essential output") flag.BoolVarP(&settings.Silent, "silent", "S", settings.Silent, "Suppress all non-essential output")
flag.BoolVarP(&settings.SpoofEmail, "spoof-email", "", true, "Spoof email (only for email mode)") flag.BoolVarP(&settings.SpoofEmail, "spoof-email", "", settings.SpoofEmail, "Spoof email (only for email mode)")
flag.BoolVarP(&settings.HideAvatar, "hide-avatar", "a", false, "Hide the avatar in the output") flag.BoolVarP(&settings.PrintAvatar, "print-avatar", "a", settings.PrintAvatar, "Show the avatar in the output")
flag.StringVarP(&settings.JsonOutput, "json", "j", "", "Write results to specified JSON file") flag.StringVarP(&settings.JsonOutput, "json", "j", settings.JsonOutput, "Write results to specified JSON file")
//// Parse //// Parse
flag.Parse() flag.Parse()
//// Setup
settings.Client = github.NewClient(nil)
settings.Logger = log.NewWithOptions(os.Stderr, log.Options{
ReportCaller: false,
ReportTimestamp: false,
})
settings.Ctx = context.WithValue(context.Background(), github.SleepUntilPrimaryRateLimitResetWhenRateLimited, true)
//// Tail //// Tail
nonFlagArgs := flag.Args() nonFlagArgs := flag.Args()
if len(nonFlagArgs) > 1 { if len(nonFlagArgs) > 1 {
settings.Logger.Error("Please provide only one target (username or email)") settings.Logger.Error("Please provide only one target (username or email)")
flag.Usage() flag.Usage()
os.Exit(1) os.Exit(1)
} else if len(nonFlagArgs) < 1 { } else if len(nonFlagArgs) == 0 {
settings.Logger.Error("Please provide a target (username or email)") settings.Logger.Error("Please provide a target (username or email)")
flag.Usage() flag.Usage()
os.Exit(1) os.Exit(1)
@@ -133,7 +152,7 @@ func GetSettings() (settings Settings) {
settings.Target = strings.TrimPrefix(settings.Target, "@") // Remove the @ of the username settings.Target = strings.TrimPrefix(settings.Target, "@") // Remove the @ of the username
if strings.Contains(settings.Target, " ") { if strings.Contains(settings.Target, " ") {
settings.Logger.Fatal("Target cannot contain spaces") err = fmt.Errorf("target cannot contain spaces")
} }
if strings.Contains(settings.Target, "@") { if strings.Contains(settings.Target, "@") {
@@ -143,11 +162,11 @@ func GetSettings() (settings Settings) {
} }
// If token is not set via flag, get it from env // If token is not set via flag, get it from env
if settings.Token == "null" { if settings.Token == "null" || settings.Token == "" {
settings.Token = getToken() settings.Token = GetToken()
} }
if settings.Token == "null" { if settings.Token == "null" || settings.Token == "" {
settings.Logger.Warn("No Github token provided. You might hit the rate limit. Check the help menu for more information.") settings.Logger.Warn("No Github token provided. You might hit the rate limit. Check the help menu for more information.")
} else { } else {
settings.Client = settings.Client.WithAuthToken(settings.Token) settings.Client = settings.Client.WithAuthToken(settings.Token)
+2 -1
View File
@@ -9,7 +9,8 @@ import (
flag "github.com/spf13/pflag" flag "github.com/spf13/pflag"
) )
func getToken() string { // GetToken retrieves the GitHub token from the environment variable or config file
func GetToken() string {
token := os.Getenv("GITHUB_RECON_TOKEN") token := os.Getenv("GITHUB_RECON_TOKEN")
if token != "" { if token != "" {
return token return token
+4 -2
View File
@@ -57,7 +57,9 @@ func PrintStruct(settings github_recon_settings.Settings, s any, indent int) {
for i := 0; i < v.NumField(); i++ { for i := 0; i < v.NumField(); i++ {
field := t.Field(i).Name field := t.Field(i).Name
value := v.Field(i) value := v.Field(i)
if !value.CanInterface() {
continue
}
if !value.IsValid() || (value.Kind() == reflect.String && value.String() == "") { if !value.IsValid() || (value.Kind() == reflect.String && value.String() == "") {
continue continue
} }
@@ -143,7 +145,7 @@ func PrintTitle(silent bool, title string) {
} }
func PrintAvatar(settings github_recon_settings.Settings, url string) { func PrintAvatar(settings github_recon_settings.Settings, url string) {
if settings.HideAvatar || url == "" || settings.Silent { if !settings.PrintAvatar || url == "" || settings.Silent {
return return
} }