class FindGithubEmail::Finder

Finds a user's GitHub email addres by their username using GitHub's GrapQL API

Public Class Methods

find(username) click to toggle source
# File lib/find_github_email/finder.rb, line 9
def self.find(username)
  response = Client.query(
    EmailQuery,
    variables: { username: username },
    context: { bearer: GithubAccessToken.github_access_token }
  )

  raise Errors::InvalidAccessToken if response.errors.any?

  data = response.data.user&.data

  raise Errors::NoGithubUser.new(username: username) unless data

  # See spec/find_github_email/finder_spec.rb for examples of what the data
  # format looks like
  found_emails =
    ([data["email"]] +
     find_emails(data["repositories"], username) +
     find_emails(data["repositoriesContributedTo"], username) +
     find_emails(data["topRepositories"], username)).
    uniq.
    compact.
    reject { |s| s == "" || s =~ /noreply.github.com/ }

  raise Errors::NoEmailData.new(username: username) if found_emails.empty?

  found_emails
end
find_emails(data, username) click to toggle source
# File lib/find_github_email/finder.rb, line 38
def self.find_emails(data, username)
  username = username.downcase
  data["nodes"].compact.flat_map do |node|
    node["refs"]["nodes"].flat_map do |sub_node|
      author = sub_node["target"]["author"]
      login = author["user"]&.[]"login"
      if [login, author["name"]].compact.map(&:downcase).include?(username)
        author["email"]
      end
    end
  end
end