@@ -379,28 +379,44 @@ actor GitHubClient {
379379 }
380380
381381 private func trafficStats( owner: String , name: String ) async throws -> TrafficStats {
382- let token = try await validAccessToken ( )
383- let viewsURL = self . apiHost. appending ( path: " /repos/ \( owner) / \( name) /traffic/views " )
384- let clonesURL = self . apiHost. appending ( path: " /repos/ \( owner) / \( name) /traffic/clones " )
385- async let viewsPair = self . authorizedGet ( url: viewsURL, token: token)
386- async let clonesPair = self . authorizedGet ( url: clonesURL, token: token)
387- let views = try await jsonDecoder. decode ( TrafficResponse . self, from: viewsPair. 0 )
388- let clones = try await jsonDecoder. decode ( TrafficResponse . self, from: clonesPair. 0 )
389- return TrafficStats ( uniqueVisitors: views. uniques, uniqueCloners: clones. uniques)
382+ do {
383+ let token = try await validAccessToken ( )
384+ let viewsURL = self . apiHost. appending ( path: " /repos/ \( owner) / \( name) /traffic/views " )
385+ let clonesURL = self . apiHost. appending ( path: " /repos/ \( owner) / \( name) /traffic/clones " )
386+ async let viewsPair = self . authorizedGet ( url: viewsURL, token: token)
387+ async let clonesPair = self . authorizedGet ( url: clonesURL, token: token)
388+ let views = try await jsonDecoder. decode ( TrafficResponse . self, from: viewsPair. 0 )
389+ let clones = try await jsonDecoder. decode ( TrafficResponse . self, from: clonesPair. 0 )
390+ return TrafficStats ( uniqueVisitors: views. uniques, uniqueCloners: clones. uniques)
391+ } catch let error as GitHubAPIError {
392+ if case let . badStatus( code, _) = error, code == 403 {
393+ await self . diag. message ( " Traffic endpoints forbidden for \( owner) / \( name) ; skipping " )
394+ return TrafficStats ( uniqueVisitors: 0 , uniqueCloners: 0 )
395+ }
396+ throw error
397+ }
390398 }
391399
392400 private func commitHeatmap( owner: String , name: String ) async throws -> [ HeatmapCell ] {
393- let token = try await validAccessToken ( )
394- let ( data, _) = try await authorizedGet (
395- url: apiHost. appending ( path: " /repos/ \( owner) / \( name) /stats/commit_activity " ) ,
396- token: token
397- )
398- let weeks = try jsonDecoder. decode ( [ CommitActivityWeek ] . self, from: data)
399- return weeks. flatMap { week in
400- zip ( 0 ..< 7 , week. days) . map { offset, count in
401- let date = Date ( timeIntervalSince1970: TimeInterval ( week. weekStart + offset * 86400 ) )
402- return HeatmapCell ( date: date, count: count)
401+ do {
402+ let token = try await validAccessToken ( )
403+ let ( data, _) = try await authorizedGet (
404+ url: apiHost. appending ( path: " /repos/ \( owner) / \( name) /stats/commit_activity " ) ,
405+ token: token
406+ )
407+ let weeks = try jsonDecoder. decode ( [ CommitActivityWeek ] . self, from: data)
408+ return weeks. flatMap { week in
409+ zip ( 0 ..< 7 , week. days) . map { offset, count in
410+ let date = Date ( timeIntervalSince1970: TimeInterval ( week. weekStart + offset * 86400 ) )
411+ return HeatmapCell ( date: date, count: count)
412+ }
413+ }
414+ } catch let error as GitHubAPIError {
415+ if case let . badStatus( code, _) = error, code == 403 {
416+ await self . diag. message ( " Commit activity forbidden for \( owner) / \( name) ; skipping heatmap " )
417+ return [ ]
403418 }
419+ throw error
404420 }
405421 }
406422
0 commit comments