mirror of
https://github.com/anotherhadi/github-recon.git
synced 2026-10-05 19:08:24 +02:00
+109
-16
@@ -1,45 +1,138 @@
|
||||
package ghrecon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type CloseFriendsResult struct {
|
||||
Login string
|
||||
Score int
|
||||
}
|
||||
|
||||
const (
|
||||
maxFollowingForTarget = 50
|
||||
maxFollowersForFollowing = 20
|
||||
pointPerCriterion = 1
|
||||
)
|
||||
|
||||
// CloseFriends returns a list of close friends of the user
|
||||
// To derive this, we check the following:
|
||||
// 1. The target has less than 50 Following
|
||||
// 2. The target's following has less than 20 followers
|
||||
|
||||
// 2. The target's following has less than 20 followers (+1 point)
|
||||
// 3. The target's following follows the target (+1 point)
|
||||
func (r Recon) CloseFriends(username string) (response []CloseFriendsResult) {
|
||||
r.PrintTitle("🧑🤝🧑 Close Friends")
|
||||
|
||||
following, resp, err := r.client.Users.ListFollowing(r.ctx, username, nil)
|
||||
if err != nil {
|
||||
r.logger.Fatal("Failed to fetch user's close friends", "err", err)
|
||||
}
|
||||
if len(following) > 50 {
|
||||
r.PrintInfo("INFO", "No commits found")
|
||||
r.logger.Error("Failed to fetch user's following list", "user", username, "err", err)
|
||||
r.PrintNewline()
|
||||
return []CloseFriendsResult{}
|
||||
return
|
||||
}
|
||||
WaitForRateLimit(resp)
|
||||
for _, user := range following {
|
||||
followers, resp, err := r.client.Users.Get(r.ctx, user.GetLogin())
|
||||
WaitForRateLimit(resp)
|
||||
if err != nil {
|
||||
|
||||
if len(following) >= maxFollowingForTarget {
|
||||
r.PrintInfo(
|
||||
"INFO",
|
||||
fmt.Sprintf(
|
||||
"%s follows %d or more users (%d). Skipping close friends check.",
|
||||
username,
|
||||
maxFollowingForTarget,
|
||||
len(following),
|
||||
),
|
||||
)
|
||||
r.PrintNewline()
|
||||
return
|
||||
}
|
||||
|
||||
if len(following) == 0 {
|
||||
r.PrintInfo("INFO", fmt.Sprintf("%s is not following anyone.", username))
|
||||
r.PrintNewline()
|
||||
return
|
||||
}
|
||||
|
||||
for _, userBeingFollowedByTarget := range following {
|
||||
loginName := userBeingFollowedByTarget.GetLogin()
|
||||
if loginName == "" {
|
||||
r.logger.Warn("User in following list has an empty login", "target_user", username)
|
||||
continue
|
||||
}
|
||||
if followers.GetFollowers() < 20 {
|
||||
|
||||
currentScore := 0
|
||||
|
||||
userDetails, userResp, userErr := r.client.Users.Get(r.ctx, loginName)
|
||||
if userErr != nil {
|
||||
r.logger.Warn(
|
||||
"Failed to fetch details for followed user",
|
||||
"followed_user",
|
||||
loginName,
|
||||
"err",
|
||||
userErr,
|
||||
)
|
||||
if userResp != nil {
|
||||
WaitForRateLimit(userResp)
|
||||
}
|
||||
continue
|
||||
}
|
||||
WaitForRateLimit(userResp)
|
||||
|
||||
if userDetails.GetFollowers() < maxFollowersForFollowing {
|
||||
currentScore += pointPerCriterion
|
||||
}
|
||||
|
||||
followsTargetBack, checkErr := r.checkIfUserFollows(loginName, username)
|
||||
if checkErr != nil {
|
||||
} else if followsTargetBack {
|
||||
currentScore += pointPerCriterion
|
||||
}
|
||||
|
||||
if currentScore > 0 {
|
||||
response = append(response, CloseFriendsResult{
|
||||
Login: user.GetLogin(),
|
||||
Score: 1,
|
||||
Login: loginName,
|
||||
Score: currentScore,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, friend := range response {
|
||||
r.PrintInfo("Username", "@"+friend.Login)
|
||||
if len(response) == 0 {
|
||||
r.PrintInfo(
|
||||
"INFO",
|
||||
fmt.Sprintf("No close friends found for %s based on the criteria.", username),
|
||||
)
|
||||
} else {
|
||||
sort.Slice(response, func(i, j int) bool {
|
||||
return response[i].Score > response[j].Score
|
||||
})
|
||||
for i, friend := range response {
|
||||
r.PrintInfo(
|
||||
fmt.Sprintf("Friend n°%d", i+1),
|
||||
"@"+friend.Login,
|
||||
"Score: "+fmt.Sprintf("%d", friend.Score),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
r.PrintNewline()
|
||||
return
|
||||
}
|
||||
|
||||
// checkIfUserFollows checks if sourceUserLogin follows targetUserLogin.
|
||||
func (r Recon) checkIfUserFollows(sourceUserLogin, targetUserLogin string) (bool, error) {
|
||||
isFollowing, resp, err := r.client.Users.IsFollowing(r.ctx, sourceUserLogin, targetUserLogin)
|
||||
if err != nil {
|
||||
r.logger.Warn("Error checking if user follows target",
|
||||
"source_user_checking", sourceUserLogin,
|
||||
"target_user_to_check", targetUserLogin,
|
||||
"err", err)
|
||||
if resp != nil {
|
||||
WaitForRateLimit(resp)
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
if resp != nil {
|
||||
WaitForRateLimit(resp)
|
||||
}
|
||||
return isFollowing, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user