@@ -23,15 +23,41 @@ let httpGet url =
2323 |> getResponse
2424 |> Job.bind Response.readBodyAsString
2525
26- let host = " https://api.github.com"
27- let userUrl = sprintf " %s /users/%s " host
26+ type GitHubResponse = {
27+ Body : string
28+ NextPageUrl : string option
29+ }
30+
31+ let getNextPageUrl ( linkText : string ) =
32+ linkText.Split([| ',' |])
33+ |> Array.map ( fun l -> l.Split([| ';' |]))
34+ |> Array.tryFind( fun l -> l.Length = 2 && l.[ 1 ]. Contains( " next" ))
35+ |> Option.map( fun l -> l.[ 0 ]. Trim() .TrimStart( '<' ) .TrimEnd( '>' ))
36+
37+ let gitHubResponse response = job {
38+ let! body = Response.readBodyAsString response
39+ let nextPageUrl =
40+ match response.headers.TryFind( ResponseHeader.Link) with
41+ | Some linkText -> getNextPageUrl linkText
42+ | None -> None
43+ return { Body = body; NextPageUrl = nextPageUrl}
44+ }
45+
46+ let httpGetWithPagination url =
47+ Request.createUrl Get url
48+ |> Request.setHeader ( UserAgent " FsHopac" )
49+ |> getResponse
50+ |> Job.bind gitHubResponse
51+
52+ let basePath = " https://api.github.com"
53+ let userUrl = sprintf " %s /users/%s " basePath
2854
2955let getUser username : Job < User > =
3056 userUrl username
3157 |> httpGet
3258 |> Job.map UserTypeProvider.Parse
3359
34- let userReposUrl = sprintf " %s /users/%s /repos" host
60+ let userReposUrl = sprintf " %s /users/%s /repos?per_page=100 " basePath
3561
3662let topThreeUserRepos ( repos : Repo []) =
3763 let takeCount =
@@ -42,14 +68,30 @@ let topThreeUserRepos (repos : Repo []) =
4268 |> Array.sortByDescending ( fun repo -> repo.StargazersCount)
4369 |> Array.take takeCount
4470
71+ let getUserAllRepos username =
72+ let rec getUserAllRepos ' url ( repos : Repo list ) = job {
73+ let! gitHubResponse =
74+ httpGetWithPagination url
75+ let currentPageRepos =
76+ gitHubResponse.Body
77+ |> ReposTypeProvider.Parse
78+ |> Array.toList
79+ let reposSoFar = repos @ currentPageRepos
80+ match gitHubResponse.NextPageUrl with
81+ | Some nextPageUrl ->
82+ return ! getUserAllRepos' nextPageUrl reposSoFar
83+ | None -> return reposSoFar
84+ }
85+ getUserAllRepos' ( userReposUrl username) []
86+ |> Job.map ( List.toArray)
87+
4588let getTopThreeUserRepos username : Job < Repo []> =
46- userReposUrl username
47- |> httpGet
48- |> Job.map ReposTypeProvider.Parse
89+ getUserAllRepos username
4990 |> Job.map topThreeUserRepos
5091
92+
5193let languagesUrl userName repoName =
52- sprintf " %s /repos/%s /%s /languages" host userName repoName
94+ sprintf " %s /repos/%s /%s /languages" basePath userName repoName
5395
5496let parseLanguagesJson languagesJson =
5597 languagesJson
@@ -98,4 +140,8 @@ let getUserDto username = job {
98140 AvatarUrl = user.AvatarUrl
99141 TopThreeRepos = repoDtos.ToArray()
100142 }
101- }
143+ }
144+
145+ #time " on"
146+ getUserDto " haf" |> run
147+ #time " off"
0 commit comments