A curated list of libraries & SDKs for the Bluesky API and AT Protocol
at master 4.9 kB view raw
1require_relative 'npm_import' 2require_relative 'requests' 3require 'base64' 4 5class GithubImport 6 include Requests 7 8 def initialize 9 @user_cache = {} 10 end 11 12 def request_headers 13 { 'Authorization' => "Bearer " + auth_config['github_token'] } 14 end 15 16 def url_matches?(url) 17 url =~ %r{^https://github\.com/[\w\-\.]+/[\w\-\.]+} 18 end 19 20 def import_url(url) 21 url =~ %r{^https://github\.com/([\w\-\.]+)/([\w\-\.]+)} 22 user, repo = $1, $2 23 24 repo_info = get_repo_info(user, repo) 25 data = extract_repo_data(repo_info) 26 27 if release = get_latest_release(user, repo) 28 data['last_release'] = release 29 end 30 31 if tag_info = get_latest_tag(user, repo) 32 data['last_tag'] = tag_info 33 end 34 35 if ['JavaScript', 'TypeScript'].include?(repo_info['language']) 36 npm = get_npm_releases(user, repo) 37 last_update = npm.map { |n| n.last_release_time }.sort.last 38 39 if last_update && (release.nil? || last_update > release['published_at']) 40 data['last_release'] = { 'published_at' => last_update } 41 end 42 end 43 44 data['last_commit'] = get_latest_commit(user, repo) 45 46 if user_info = get_user_info(user) 47 data['user_name'] = user_info['name'] 48 end 49 50 data 51 end 52 53 def get_repo_info(user, repo) 54 response = get_response("https://api.github.com/repos/#{user}/#{repo}") 55 raise FetchError.new(response) unless response.code.to_i == 200 56 57 JSON.parse(response.body) 58 end 59 60 def extract_repo_data(json) 61 data = { 62 'name' => json['name'], 63 'description' => json['description'], 64 'user_login' => json['owner']['login'], 65 'user_profile' => "https://github.com/#{json['owner']['login']}", 66 'homepage' => json['homepage'], 67 'stars' => json['stargazers_count'] 68 } 69 70 if json['license'] && json['license']['spdx_id'] != 'NOASSERTION' 71 data['license'] = json['license']['spdx_id'] 72 end 73 74 data 75 end 76 77 def get_latest_release(user, repo) 78 response = get_response("https://api.github.com/repos/#{user}/#{repo}/releases/latest") 79 80 if response.code.to_i == 200 81 json = JSON.parse(response.body) 82 83 { 84 'tag_name' => json['tag_name'], 85 'name' => json['name'], 86 'draft' => json['draft'], 87 'prerelease' => json['prerelease'], 88 'created_at' => Time.parse(json['created_at']), 89 'published_at' => Time.parse(json['published_at']) 90 } 91 elsif response.code.to_i == 404 92 nil 93 else 94 raise FetchError.new(response) 95 end 96 end 97 98 def get_latest_tag(user, repo) 99 response = get_response("https://api.github.com/repos/#{user}/#{repo}/tags") 100 raise FetchError.new(response) unless response.code.to_i == 200 101 102 json = JSON.parse(response.body) 103 104 if tag = json.first 105 tag_name = tag['name'] 106 response = get_response(tag['commit']['url']) 107 raise FetchError.new(response) unless response.code.to_i == 200 108 109 json = JSON.parse(response.body) 110 { 111 'name' => tag_name, 112 'author_date' => Time.parse(json['commit']['author']['date']), 113 'committer_date' => Time.parse(json['commit']['committer']['date']) 114 } 115 else 116 nil 117 end 118 end 119 120 def get_latest_commit(user, repo) 121 response = get_response("https://api.github.com/repos/#{user}/#{repo}/commits") 122 raise FetchError.new(response) unless response.code.to_i == 200 123 124 json = JSON.parse(response.body) 125 126 if commit = json.first 127 { 128 'author_date' => Time.parse(commit['commit']['author']['date']), 129 'committer_date' => Time.parse(commit['commit']['committer']['date']) 130 } 131 else 132 raise FetchError.new(response) 133 end 134 end 135 136 def get_user_info(user) 137 @user_cache[user] ||= begin 138 response = get_response("https://api.github.com/users/#{user}") 139 raise FetchError.new(response) unless response.code.to_i == 200 140 141 JSON.parse(response.body) 142 end 143 end 144 145 def get_npm_releases(user, repo) 146 sleep 5 147 148 search_url = URI("https://api.github.com/search/code") 149 search_url.query = URI.encode_www_form(q: "repo:#{user}/#{repo} filename:package.json", per_page: 100) 150 response = get_response(search_url) 151 raise FetchError.new(response) unless response.code.to_i == 200 152 153 json = JSON.parse(response.body) 154 releases = [] 155 156 json['items'].each do |file| 157 response = get_response(file['url']) 158 raise FetchError.new(response) unless response.code.to_i == 200 159 160 details = JSON.parse(response.body) 161 contents = Base64.decode64(details['content']) 162 package = NPMImport::LocalPackage.new(JSON.parse(contents)) 163 164 next if package.version.nil? || package.private? 165 166 if npm = NPMImport.new.get_package_info(package.name) 167 if npm.repository_url =~ %r{://github\.com/#{Regexp.escape(user)}/#{Regexp.escape(repo)}(\.git)?$} 168 releases << npm 169 end 170 end 171 end 172 173 releases 174 end 175end