11package nobori
22
33import (
4+ "context"
45 "log"
56 "net/http"
67 "os"
@@ -9,18 +10,27 @@ import (
910 "strings"
1011 "time"
1112
13+ ql "github.com/hasura/go-graphql-client"
1214 "github.com/terrapkg/gura/db"
15+ "github.com/terrapkg/gura/util"
1316)
1417
1518// ? https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#about-secondary-rate-limits
1619// no more than 100 parallel requests
1720var pool = make (chan db.Stream , 100 )
1821var tokens []Token
22+ var ql_current_token Token
23+ var qlcli = ql .NewClient ("https://api.github.com/graphql" , http .DefaultClient ).WithRequestModifier (
24+ func (r * http.Request ) {
25+ r .Header .Add ("Authorization" , "Bearer" + ql_current_token .key )
26+ })
1927
2028type Token struct {
2129 key string
2230 quota int16
2331 reset time.Time
32+ qlquo int16
33+ qlrst time.Time
2434}
2535
2636func fetchGitHub (stream db.Stream ) {
@@ -100,12 +110,12 @@ func waitForFish(token Token) {
100110func updToken (token * Token , resp * http.Response ) {
101111 quota , err := strconv .ParseInt (resp .Header .Get ("x-ratelimit-remaining" ), 10 , 16 )
102112 if err != nil {
103- log .Fatalf ("github: strconv x-ratelimit-remaining: %v" , err , * token )
113+ log .Fatalf ("github: strconv x-ratelimit-remaining: %v" , err )
104114 return
105115 }
106116 reset , err := strconv .ParseInt (resp .Header .Get ("x-ratelimit-reset" ), 10 , 64 )
107117 if err != nil {
108- log .Fatalf ("github: strconv x-ratelimit-reset: %v" , err , * token )
118+ log .Fatalf ("github: strconv x-ratelimit-reset: %v" , err )
109119 return
110120 }
111121 token .quota = int16 (quota )
@@ -119,19 +129,93 @@ func swimGitHub() {
119129 waitForFish (token )
120130 for {
121131 stream := <- pool
122- req , err := http .NewRequest (http .MethodGet , "https://api.github.com/repos/" + stream .Fetch + "/tags" , nil )
123- if err != nil {
124- log .Printf ("github: req [%s]: %v" , stream .Fetch , err )
125- continue
126- }
127- req .Header .Add ("Authorization" , "Bearer " + token .key )
128- resp , err := http .DefaultClient .Do (req )
129- if err != nil {
130- log .Printf ("github: resp [%s]: %v" , stream .Fetch , err )
131- continue
132- }
133- updToken (& token , resp )
134- // TODO: update stream
132+ go func (stream db.Stream ) {
133+ fetch (& stream )
134+ go schedule (stream )
135+ db .DB .Save (stream )
136+ }(stream )
135137 }
136138 }
137139}
140+
141+ /*
142+ func rest_tag(stream *db.Stream) {
143+ req, err := http.NewRequest(http.MethodGet, "https://api.github.com/repos/"+stream.Fetch+"/tags", nil)
144+ if err != nil {
145+ log.Printf("github: req [%s]: %v", stream.Fetch, err)
146+ continue
147+ }
148+ req.Header.Add("Authorization", "Bearer "+token.key)
149+ resp, err := http.DefaultClient.Do(req)
150+ if err != nil {
151+ log.Printf("github: resp [%s]: %v", stream.Fetch, err)
152+ continue
153+ }
154+ updToken(&token, resp)
155+ buf, err := io.ReadAll(resp.Body)
156+ if err != nil {
157+ log.Fatalln("github: can't read buf")
158+ }
159+ var v []struct {
160+ name string
161+ }
162+ json.Unmarshal(buf, &v)
163+ if stream.Ver != v[0].name {
164+ stream.Ver = v[0].name
165+ stream.LastUpd = time.Now()
166+ }
167+ }*/
168+
169+ type GHFetchType = int8
170+
171+ const (
172+ TAG GHFetchType = iota
173+ RELEASE
174+ QL
175+ )
176+
177+ // ? https://stackoverflow.com/questions/19452244/github-api-v3-order-tags-by-creation-date
178+ type TagQL struct {
179+ Repository struct {
180+ Refs struct {
181+ edges []struct {
182+ node struct {
183+ name string
184+ }
185+ }
186+ } `graphql:"refs(prefix: \"refs/tags/\", last: 1, orderBy: {field: TAG_COMMIT_DATE, direction: ASC}, before: $before), query: $prefix"`
187+ } `graphql:"repository(owner: $owner, name: $name)"`
188+ }
189+
190+ func fetch (stream * db.Stream ) {
191+ s , remain := util .SplitOnce (stream .Fetch , ' ' )
192+ i , err := strconv .Atoi (s )
193+ if err != nil {
194+ panic (err )
195+ }
196+ // TODO: support other GHFetchType
197+ switch GHFetchType (i ) {
198+ case TAG :
199+ ql_tag (stream , remain )
200+ }
201+ stream .LastChk = time .Now ()
202+ }
203+
204+ func ql_tag (stream * db.Stream , remain string ) {
205+ prefix , remain := util .SplitOnce (remain , ' ' )
206+ owner , name := util .SplitOnce (remain , '/' )
207+ var q TagQL
208+ if err := qlcli .Query (context .Background (), & q , map [string ]any {
209+ "prefix" : prefix ,
210+ "before" : nil ,
211+ "owner" : owner ,
212+ "name" : name ,
213+ }); err != nil {
214+ log .Printf ("github: ql_tag: %v" , err )
215+ return
216+ }
217+ if v := strings .TrimPrefix (q .Repository .Refs .edges [0 ].node .name , prefix ); v != stream .Ver {
218+ stream .Ver = v
219+ stream .LastUpd = time .Now ()
220+ }
221+ }
0 commit comments