Skip to content

Commit 8f68812

Browse files
authored
Merge pull request mouredev#7182 from hozlucas28/Solution-45-Go
mouredev#45 - Go
2 parents ad67d96 + f19ff13 commit 8f68812

File tree

1 file changed

+264
-0
lines changed

1 file changed

+264
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"fmt"
7+
"io"
8+
"net/http"
9+
"os"
10+
"os/exec"
11+
)
12+
13+
/* -------------------------------------------------------------------------- */
14+
/* STRUCTS */
15+
/* -------------------------------------------------------------------------- */
16+
17+
/* -------------------------------- Adapters -------------------------------- */
18+
19+
type Adapter struct{}
20+
21+
func (_ *Adapter) UserData(userData *User) *UserData {
22+
var forks uint = 0
23+
for _, publicRepo := range userData.PublicRepositoriesData {
24+
if publicRepo.Fork {
25+
forks++
26+
}
27+
}
28+
29+
return &UserData{
30+
Followers: userData.Followers,
31+
Following: userData.Following,
32+
Forks: forks,
33+
Name: userData.Name,
34+
PublicRepositories: userData.PublicRepositories,
35+
Stars: uint(len(userData.Stars)),
36+
UserName: userData.Login,
37+
}
38+
39+
}
40+
41+
/* ------------------------------- GitHub API ------------------------------- */
42+
43+
type PublicRepositories struct {
44+
Fork bool `json:"fork"`
45+
}
46+
47+
type Stars struct {
48+
Url string `json:"url"`
49+
}
50+
51+
type User struct {
52+
Followers uint `json:"followers"`
53+
Following uint `json:"following"`
54+
Login string `json:"login"`
55+
Name string `json:"name"`
56+
PublicRepositories uint `json:"public_repos"`
57+
ReposUrl string `json:"repos_url"`
58+
PublicRepositoriesData []PublicRepositories `json:"public_repos_data"`
59+
Stars []Stars `json:"stars"`
60+
}
61+
62+
type GitHubAPI struct {
63+
User User
64+
}
65+
66+
/* ------------------------------ GitHubService ----------------------------- */
67+
68+
type UserData struct {
69+
Followers uint `json:"followers"`
70+
Following uint `json:"following"`
71+
Forks uint `json:"forks"`
72+
Name string `json:"name"`
73+
PublicRepositories uint `json:"public_repositories"`
74+
Stars uint `json:"stars"`
75+
UserName string `json:"userName"`
76+
}
77+
78+
type GitHubService interface {
79+
GetUserData(userName string) (*UserData, error)
80+
}
81+
82+
type githubService struct {
83+
accessToken string
84+
_ struct{}
85+
}
86+
87+
func NewGitHubService(accessToken string) GitHubService {
88+
var githubService githubService = githubService{accessToken: accessToken}
89+
return &githubService
90+
}
91+
92+
func (githubService *githubService) GetUserData(userName string) (*UserData, error) {
93+
var userData User
94+
var adapter Adapter
95+
96+
var err error
97+
var errMsg string
98+
99+
var client *http.Client = &http.Client{}
100+
var request *http.Request
101+
102+
var headers map[string][]string = map[string][]string{
103+
"Authorization": {fmt.Sprintf("Bearer %s", githubService.accessToken)},
104+
"Accept": {"application/vnd.github+json"},
105+
"X-GitHub-Api-Version": {"2022-11-28"},
106+
}
107+
108+
var response *http.Response
109+
var starsData []Stars
110+
var publicReposData []PublicRepositories
111+
112+
request, err = http.NewRequest("GET", fmt.Sprintf("https://api.github.com/users/%s", userName), nil)
113+
if err != nil {
114+
return &UserData{}, err
115+
}
116+
117+
request.Header = headers
118+
119+
response, err = client.Do(request)
120+
if err != nil {
121+
return &UserData{}, err
122+
}
123+
124+
if response.StatusCode == http.StatusOK {
125+
body, err := io.ReadAll(response.Body)
126+
if err != nil {
127+
return &UserData{}, err
128+
}
129+
130+
err = json.Unmarshal(body, &userData)
131+
if err != nil {
132+
return &UserData{}, err
133+
}
134+
135+
} else {
136+
errMsg = fmt.Sprintf("%s: %v", request.Response.Status, request.Response.Body)
137+
return &UserData{}, errors.New(errMsg)
138+
}
139+
140+
request, err = http.NewRequest("GET", fmt.Sprintf("https://api.github.com/users/%s/starred", userName), nil)
141+
if err != nil {
142+
return &UserData{}, err
143+
}
144+
145+
request.Header = headers
146+
147+
response, err = client.Do(request)
148+
if err != nil {
149+
return &UserData{}, err
150+
}
151+
152+
if response.StatusCode == http.StatusOK {
153+
body, err := io.ReadAll(response.Body)
154+
if err != nil {
155+
return &UserData{}, err
156+
}
157+
158+
err = json.Unmarshal(body, &starsData)
159+
if err != nil {
160+
return &UserData{}, err
161+
}
162+
163+
userData.Stars = starsData
164+
} else {
165+
errMsg = fmt.Sprintf("%s: %v", request.Response.Status, request.Response.Body)
166+
return &UserData{}, errors.New(errMsg)
167+
}
168+
169+
request, err = http.NewRequest("GET", userData.ReposUrl, nil)
170+
if err != nil {
171+
return &UserData{}, err
172+
}
173+
174+
request.Header = headers
175+
176+
response, err = client.Do(request)
177+
if err != nil {
178+
return &UserData{}, err
179+
}
180+
181+
if response.StatusCode == http.StatusOK {
182+
body, err := io.ReadAll(response.Body)
183+
if err != nil {
184+
return &UserData{}, err
185+
}
186+
187+
err = json.Unmarshal(body, &publicReposData)
188+
if err != nil {
189+
return &UserData{}, err
190+
}
191+
192+
userData.PublicRepositoriesData = publicReposData
193+
} else {
194+
errMsg = fmt.Sprintf("%s: %v", request.Response.Status, request.Response.Body)
195+
return &UserData{}, errors.New(errMsg)
196+
}
197+
198+
return adapter.UserData(&userData), err
199+
}
200+
201+
/* -------------------------------------------------------------------------- */
202+
/* MAIN */
203+
/* -------------------------------------------------------------------------- */
204+
205+
func main() {
206+
const accessToken string = "XXX" // Complete with your personal GitHub Access Token.
207+
var githubService GitHubService = NewGitHubService(accessToken)
208+
209+
var userInput string
210+
211+
var userData *UserData
212+
var err error
213+
214+
var cmd *exec.Cmd
215+
216+
var i int
217+
var padding int
218+
219+
fmt.Print("> Enter a GitHub username (-1 to exit): ")
220+
fmt.Scanf("%s\n", &userInput)
221+
222+
for userInput != "-1" {
223+
userData, err = githubService.GetUserData(userInput)
224+
225+
if err == nil {
226+
cmd = exec.Command("clear")
227+
cmd.Stdout = os.Stdout
228+
cmd.Run()
229+
230+
fmt.Print("+ ")
231+
for i = 0; i < 52; i++ {
232+
fmt.Print("-")
233+
}
234+
fmt.Print(" +\n")
235+
236+
padding = len(userData.UserName) - 52
237+
fmt.Printf("+ %-*s%s%*s +\n", padding/2, "", userData.UserName, padding/2+padding%2, "")
238+
239+
fmt.Print("+ ")
240+
for i = 0; i < 52; i++ {
241+
fmt.Print("-")
242+
}
243+
fmt.Print(" +\n")
244+
245+
fmt.Printf("+ %-52s +\n", fmt.Sprintf("%s: %s.", "Name", userData.Name))
246+
fmt.Printf("+ %-52s +\n", fmt.Sprintf("%s: %d.", "Public repositories", userData.PublicRepositories))
247+
fmt.Printf("+ %-52s +\n", fmt.Sprintf("%s: %d.", "Repositories stared", userData.Stars))
248+
fmt.Printf("+ %-52s +\n", fmt.Sprintf("%s: %d.", "Number of repositories forked", userData.Forks))
249+
fmt.Printf("+ %-52s +\n", fmt.Sprintf("%s: %d.", "Following", userData.Following))
250+
fmt.Printf("+ %-52s +\n", fmt.Sprintf("%s: %d.", "Followers", userData.Followers))
251+
252+
fmt.Print("+ ")
253+
for i = 0; i < 52; i++ {
254+
fmt.Print("-")
255+
}
256+
fmt.Print(" +\n")
257+
} else {
258+
fmt.Println("\n> An error occurred on fetch '{user_input}' username! Try again...")
259+
}
260+
261+
fmt.Print("\n> Enter a GitHub username (-1 to exit): ")
262+
fmt.Scanf("%s\n", &userInput)
263+
}
264+
}

0 commit comments

Comments
 (0)