github_favorite_language 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 437ba989c8bc8ebb3526acbfcdad3fec0ff07cf3
4
+ data.tar.gz: 0fcd07bd693590b670bbf73e63a457e4452fd902
5
+ SHA512:
6
+ metadata.gz: e0bdb00281020b4b85ed6334bffb0d3b996acffdbaa3fa8909c607c1d91cc06406c213dd230292dc4b629c26c7e2697a8b7e0ae14dfa837750d71ff7a09df4de
7
+ data.tar.gz: 44594fbfdf4262baf8276eea1d9357bed08e4130c48ce3aefad70cf9397bc18f8ce91af2d862f15fb0dac436d2b01e0abf08fdb994d76eabb2da1650247a3920
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ .ruby-gemset
12
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
4
+ before_install: gem install bundler -v 1.10.4
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in github_favorite_language.gemspec
4
+ gemspec
5
+
6
+ gem "coveralls", require: false
data/Guardfile ADDED
@@ -0,0 +1,43 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ # Note: The cmd option is now required due to the increasing number of ways
19
+ # rspec may be run, below are examples of the most common uses.
20
+ # * bundler: 'bundle exec rspec'
21
+ # * bundler binstubs: 'bin/rspec'
22
+ # * spring: 'bin/rspec' (This will use spring if running and you have
23
+ # installed the spring binstubs per the docs)
24
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
25
+ # * 'just' rspec: 'rspec'
26
+
27
+ guard :rspec, cmd: "bundle exec rspec" do
28
+ require "guard/rspec/dsl"
29
+ dsl = Guard::RSpec::Dsl.new(self)
30
+
31
+ # Feel free to open issues for suggestions and improvements
32
+
33
+ # RSpec files
34
+ # watch /lib/ files
35
+ watch(%r{^lib/(.+).rb$}) do |m|
36
+ ["spec/#{m[1]}_spec.rb", "spec/integration/#{m[1]}_integration_spec.rb"]
37
+ end
38
+
39
+ # watch /spec/ files
40
+ watch(%r{^spec/(.+).rb$}) do |m|
41
+ "spec/#{m[1]}.rb"
42
+ end
43
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Viktor Fonic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Github Favorite Language
2
+
3
+ [![Build Status](https://travis-ci.org/vfonic/github_favorite_language.svg)](https://travis-ci.org/vfonic/github_favorite_language)
4
+ [![Dependency Status](https://gemnasium.com/vfonic/github_favorite_language.svg)](https://gemnasium.com/vfonic/github_favorite_language)
5
+ [![Coverage Status](https://coveralls.io/repos/vfonic/github_favorite_language/badge.svg)](https://coveralls.io/r/vfonic/github_favorite_language)
6
+ [![Code Climate](https://codeclimate.com/github/vfonic/github_favorite_language/badges/gpa.svg)](https://codeclimate.com/github/vfonic/github_favorite_language)
7
+
8
+ Find out any GitHub user's favorite programming language!
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'github_favorite_language'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ ```bash
21
+ $ bundle
22
+ ```
23
+
24
+ Or install it yourself as:
25
+
26
+ ```bash
27
+ $ gem install github_favorite_language
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ The gem comes with the command line tool, but can be also called inside the ruby code.
33
+
34
+
35
+ Example:
36
+
37
+ Bash:
38
+
39
+ ```bash
40
+ $ github_favorite_language vfonic
41
+ ```
42
+
43
+ Ruby:
44
+
45
+ ```ruby
46
+ require 'github_favorite_language'
47
+
48
+ puts GithubFavoriteLanguage.new(username: 'vfonic').favorite_language
49
+ ```
50
+
51
+ Or:
52
+
53
+ ```ruby
54
+ require 'github_favorite_language'
55
+
56
+ GithubFavoriteLanguage.new(username: 'vfonic').print_favorite_language
57
+ ```
58
+
59
+ This will fetch vfonic repos and return the name of the main language of most repositories.
60
+ For GitHub documentation refer to: [https://developer.github.com/v3/](https://developer.github.com/v3/)
61
+
62
+
63
+ ## Development
64
+
65
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
66
+
67
+ To install this gem onto your local machine, run `bundle exec rake install`. To fix an issue, update the version number in `version.rb`, and then create a pull request.
68
+
69
+ ## License
70
+
71
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
72
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/USAGE ADDED
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Find out any GitHub user's favorite programming language
3
+
4
+ Example:
5
+ github_favorite_language vfonic
6
+
7
+ This will fetch vfonic user repos and return the name of the language
8
+ with most bytes of code written.
9
+ For GitHub documentation refer to: https://developer.github.com/v3/
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "github_favorite_language"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ require 'github_favorite_language'
3
+
4
+ if ARGV.empty? && $stdin.tty?
5
+ GithubFavoriteLanguage.print_usage
6
+ else
7
+ username = ARGV.first || STDIN.read
8
+ puts GithubFavoriteLanguage.new(username: username).print_favorite_language
9
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'github_favorite_language/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "github_favorite_language"
8
+ spec.version = GithubFavoriteLanguage::VERSION
9
+ spec.authors = ["Viktor Fonic"]
10
+ spec.email = ["viktor.fonic@gmail.com"]
11
+
12
+ spec.summary = "Find out any GitHub user's favorite language!"
13
+ spec.homepage = "https://github.com/vfonic/github_favorite_language"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.10"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", '~> 3.3.0'
24
+ end
data/lib/errors.rb ADDED
@@ -0,0 +1,16 @@
1
+ module JsonApiClient
2
+ class Error < StandardError
3
+ attr_reader :headers
4
+
5
+ def initialize(headers:, message:)
6
+ super(message)
7
+ @headers = headers
8
+ end
9
+ end
10
+
11
+ # Raised when API returns a 404 Not Found
12
+ class NotFound < Error; end
13
+
14
+ # Raised when API returns a 403 Forbidden with ratelimit remaining zero
15
+ class RateLimitExceeded < Error; end
16
+ end
data/lib/github_api.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'json_api_client'
2
+
3
+ class GithubAPI
4
+ GITHUB_API_URL = 'https://api.github.com'.freeze
5
+
6
+ def repos(user:)
7
+ repos = JsonApiClient.fetch_all_pages(url: GITHUB_API_URL + "/users/#{user}/repos")
8
+ repos.select{ |repo| repo["owner"]["login"] == user } unless repos.nil?
9
+ end
10
+ end
@@ -0,0 +1,57 @@
1
+ require 'github_api'
2
+
3
+ class GithubFavoriteLanguage
4
+ def initialize(username:)
5
+ @username = username.strip
6
+ raise UsernameWhitespaceOrEmpty if @username.empty?
7
+ @github_api = GithubAPI.new
8
+ end
9
+
10
+ def favorite_language
11
+ repos = @github_api.repos(user: @username)
12
+
13
+ languages = Hash.new(0)
14
+ repos.map do |repo|
15
+ languages[repo["language"]] += repo["size"] unless repo["language"].nil? || repo["language"].empty?
16
+ end
17
+
18
+ languages.max_by { |lang, size| size }.first unless languages.empty?
19
+ end
20
+
21
+ def print_favorite_language
22
+ begin
23
+ language = favorite_language if language.nil?
24
+
25
+ unless language.nil?
26
+ print_message(message: "#{@username}'s favorite language is: #{language}")
27
+ else
28
+ print_no_public_repos
29
+ end
30
+ rescue JsonApiClient::NotFound
31
+ print_username_not_found
32
+ rescue JsonApiClient::Error, JsonApiClient::RateLimitExceeded => e
33
+ print_message(message: e.message)
34
+ end
35
+ end
36
+
37
+ def self.print_usage
38
+ puts File.read('USAGE')
39
+ end
40
+
41
+ private
42
+
43
+ def print_message(message:)
44
+ puts message
45
+ end
46
+
47
+ def print_no_public_repos
48
+ puts "Couldn't determine #{@username}'s favorite language."
49
+ puts "Check if #{@username} has public repos with code in them."
50
+ end
51
+
52
+ def print_username_not_found
53
+ puts "User #{@username} not found. Check the username is correct."
54
+ end
55
+ end
56
+
57
+ class UsernameWhitespaceOrEmpty < StandardError; end
@@ -0,0 +1,3 @@
1
+ class GithubFavoriteLanguage
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,89 @@
1
+ # use OpenURI with caution:
2
+ # http://sakurity.com/blog/2015/02/28/openuri.htmlrequire 'open-uri'
3
+ require 'open-uri'
4
+ require 'json'
5
+ require 'errors'
6
+
7
+ # TODO: conform to JSON API spec v1.0
8
+ # http://jsonapi.org
9
+ module JsonApiClient
10
+ # Fetches all pages for the given url.
11
+ # Information about pagination is provided in the Link header of an API call.
12
+ # http://tools.ietf.org/html/rfc5988
13
+ # Example:
14
+ # Link: <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=2>; rel="next"
15
+ # <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel="last"
16
+ #
17
+ # Returns JSON parsed response body
18
+ def JsonApiClient.fetch_all_pages(url:)
19
+ headers, body = fetch_page(url: url)
20
+
21
+ return nil if headers.nil? || body.nil?
22
+
23
+ resources = JSON.parse(body)
24
+ while url = next_page(headers: headers) do
25
+ headers, body = fetch_page(url: url)
26
+ resources << JSON.parse(body)
27
+ end
28
+
29
+ resources
30
+ end
31
+
32
+ # Fetches a single page for the given url.
33
+ #
34
+ # Returns a header, body pair of response
35
+ def JsonApiClient.fetch_page(url:)
36
+ begin
37
+ res = open(URI(url))
38
+ [res.meta, res.read]
39
+ rescue OpenURI::HTTPError => e
40
+ process_error e
41
+ end
42
+ end
43
+
44
+ # Abstract OpenURI::HTTPErrors so we can:
45
+ # - provide more information
46
+ # - replace it later if needed
47
+ #
48
+ # Raises new error containing any additional valuable information.
49
+ def JsonApiClient.process_error(error)
50
+ headers = error.io.meta
51
+ if error.message == '404 Not Found'
52
+ raise JsonApiClient::NotFound.new(headers: headers, message: 'Not Found')
53
+ elsif error.message == '403 Forbidden'
54
+ # Rate Limit Remaining examples: http://stackoverflow.com/a/16022625
55
+ ratelimit_remaining = headers["x-ratelimit-userremaining"] ||
56
+ headers["x-ratelimit-remaining"] ||
57
+ headers["x-rate-limit-remaining"]
58
+
59
+ if ratelimit_remaining.to_i == 0
60
+ ratelimit_reset = headers["x-ratelimit-reset"] ||
61
+ headers["x-rate-limit-reset"] ||
62
+ headers["x-ratelimit-userreset"]
63
+ message = 'Rate limit exceeded.'
64
+
65
+ if ratelimit_reset
66
+ ratelimit_reset_time = Time.at(ratelimit_reset.to_i)
67
+ message += " Try again after #{ratelimit_reset_time}."
68
+ end
69
+ api_error = JsonApiClient::RateLimitExceeded.new(headers: headers,
70
+ message: message)
71
+ raise api_error
72
+ end
73
+ end
74
+
75
+ raise JsonApiClient::Error.new(headers: headers, message: error.message)
76
+ end
77
+
78
+ # Finds next page from 'Link' response header
79
+ #
80
+ # Returns a url of next page
81
+ def JsonApiClient.next_page(headers:)
82
+ link = (headers["Link"] || "").split(', ').map do |link|
83
+ href, name = link.match(/<(.*?)>; rel="(\w+)"/).captures
84
+ return href if name == 'next'
85
+ end
86
+
87
+ nil
88
+ end
89
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: github_favorite_language
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Viktor Fonic
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-07-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.3.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.3.0
55
+ description:
56
+ email:
57
+ - viktor.fonic@gmail.com
58
+ executables:
59
+ - github_favorite_language
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".rspec"
65
+ - ".travis.yml"
66
+ - CODE_OF_CONDUCT.md
67
+ - Gemfile
68
+ - Guardfile
69
+ - LICENSE.txt
70
+ - README.md
71
+ - Rakefile
72
+ - USAGE
73
+ - bin/console
74
+ - bin/rake
75
+ - bin/setup
76
+ - exe/github_favorite_language
77
+ - github_favorite_language.gemspec
78
+ - lib/errors.rb
79
+ - lib/github_api.rb
80
+ - lib/github_favorite_language.rb
81
+ - lib/github_favorite_language/version.rb
82
+ - lib/json_api_client.rb
83
+ homepage: https://github.com/vfonic/github_favorite_language
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.4.6
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Find out any GitHub user's favorite language!
107
+ test_files: []