codebadges 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/Gemfile +2 -2
- data/LICENSE.txt +21 -0
- data/README.md +22 -15
- data/Rakefile +2 -2
- data/bin/codebadges +1 -1
- data/codebadges.gemspec +9 -7
- data/lib/codebadges/badges.rb +19 -25
- data/lib/codebadges/courses.rb +25 -0
- data/lib/codebadges/version.rb +2 -1
- data/lib/codebadges.rb +1 -0
- data/spec/badges_spec.rb +30 -0
- data/spec/courses_spec.rb +30 -0
- data/spec/fixtures/badges.yml +75 -0
- data/spec/fixtures/courses.yml +17 -0
- data/spec/fixtures/vcr_cassettes/badges.yml +1202 -0
- data/spec/fixtures/vcr_cassettes/courses.yml +1367 -0
- metadata +52 -13
- data/spec/badges_test.rb +0 -115
- data/spec/testfiles/test.txt +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c22abfa1d1de1379c39807dd72bd53b331a011b
|
4
|
+
data.tar.gz: 3674c115ef9068fb5152085a23d14d39d6a731ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4715c01e03c0776b9f32b6be4a25f36c634feb3c07c52271fcafd1bdddf1e1938b60108b0de1253ee12fcabe4585ca06d3ffab280036961f57be66293f5c72e9
|
7
|
+
data.tar.gz: 94ba8ce903b4290bebffc9ece7cb31a9f2c7428176b7353d9660613960f52564fb3f9c3c995105086c13e67bd60380c9de75aabae1490bd300b6ca56930a8f23
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Soumya Ray, Chen Li-Zhan
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,24 +1,31 @@
|
|
1
|
-
CodeBadges
|
2
|
-
===============
|
1
|
+
# CodeBadges [![Build Status](https://travis-ci.org/ISS-SOA/Codecademy-Ruby.svg?branch=develop)](https://travis-ci.org/ISS-SOA/Codecademy-Ruby)
|
3
2
|
|
4
|
-
|
3
|
+
Codecademy is a great place to learn coding! Unfortunately, Codecademy's website
|
4
|
+
doesn't provide an API to help us monitor our own coding.
|
5
|
+
So we made the CodeBadges gem to scrape user achievements from Codecademy!
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
Once you done a section of course on the Codecademy(The online programming tutorial), you will get a badges.
|
9
|
-
The gem is to understand that what course and the level the user take on the Codecademy.
|
7
|
+
Note that we respect Codecademy's `robots.txt`
|
10
8
|
|
11
9
|
## Usage
|
12
10
|
|
13
11
|
Install it with the following command:
|
14
|
-
|
15
|
-
gem install codebadges
|
16
|
-
|
12
|
+
```sh
|
13
|
+
$ gem install codebadges
|
14
|
+
```
|
17
15
|
|
18
|
-
|
16
|
+
Or else put it in your `Gemfile` as:
|
17
|
+
```ruby
|
18
|
+
gem codebadges
|
19
|
+
```
|
20
|
+
|
21
|
+
Run it from the command line. For example, to get the achievements of user `chenlizhan`:
|
22
|
+
```
|
23
|
+
$ codebadges chenlizhan
|
24
|
+
```
|
25
|
+
|
26
|
+
Or use it from your Ruby code:
|
19
27
|
````ruby
|
20
|
-
require
|
21
|
-
CodecademyBadges.
|
22
|
-
|
23
|
-
The argument username is the user's account who you want to check it out!
|
28
|
+
require 'codebadges'
|
29
|
+
lee = CodeBadges::CodecademyBadges.new('chenlizhan')
|
30
|
+
badges = lee.badges
|
24
31
|
````
|
data/Rakefile
CHANGED
data/bin/codebadges
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
# require '../lib/codebadges/badges.rb' # for cmd line testing purposes
|
4
3
|
require 'codebadges' # for production
|
4
|
+
# require '../lib/codebadges/badges.rb' # for cmd line testing purposes
|
5
5
|
|
6
6
|
def get_users_array_from_file(file)
|
7
7
|
users_array = []
|
data/codebadges.gemspec
CHANGED
@@ -1,21 +1,23 @@
|
|
1
|
-
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
2
|
require 'codebadges/version'
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'codebadges'
|
6
6
|
s.version = CodeBadges::VERSION
|
7
|
+
s.date = CodeBadges::DATE
|
7
8
|
s.executables << 'codebadges'
|
8
|
-
s.
|
9
|
-
s.
|
10
|
-
s.description = 'Use username as an input, automatically give you the badges the user has.'
|
9
|
+
s.summary = 'Access user and course information on Codecademy'
|
10
|
+
s.description = 'Get user achievements and course info from Codecademy'
|
11
11
|
s.authors = ['Lee Chen', 'Soumya Ray']
|
12
|
-
s.email = 'chung1350@hotmail.com'
|
12
|
+
s.email = ['chung1350@hotmail.com', 'soumya.ray@gmail.com']
|
13
13
|
s.files = `git ls-files`.split("\n")
|
14
|
-
s.test_files = `git ls-files
|
14
|
+
s.test_files = `git ls-files spec/*`.split("\n")
|
15
15
|
s.homepage = 'https://github.com/ISS-SOA/Codecademy-Ruby'
|
16
16
|
s.license = 'MIT'
|
17
17
|
|
18
18
|
s.add_development_dependency 'minitest'
|
19
19
|
s.add_development_dependency 'minitest-rg'
|
20
|
-
s.
|
20
|
+
s.add_development_dependency 'vcr'
|
21
|
+
s.add_development_dependency 'webmock'
|
22
|
+
s.add_runtime_dependency 'oga'
|
21
23
|
end
|
data/lib/codebadges/badges.rb
CHANGED
@@ -1,44 +1,38 @@
|
|
1
|
-
require '
|
1
|
+
require 'oga'
|
2
2
|
require 'open-uri'
|
3
3
|
require 'date'
|
4
|
-
|
5
|
-
# License: MIT
|
4
|
+
|
6
5
|
module CodeBadges
|
7
6
|
# This class get the user account as an input
|
8
7
|
# return a hash of user's badges information
|
9
8
|
class CodecademyBadges
|
10
|
-
TITLE_XPATH = "//div[@class = 'grid-row']//h5[@class = 'margin-top--1']"
|
11
|
-
DATE_XPATH = "//small[@class = 'text--ellipsis']"
|
12
9
|
USERS_URL = 'https://www.codecademy.com/users'
|
13
10
|
ACHIEVEMENTS_DIR = 'achievements'
|
11
|
+
ACHIEVEMENT_XPATH = "//div[contains(@class,'achievement-card')]"
|
12
|
+
ACH_TITLE_XPATH = 'h5'
|
13
|
+
ACH_DATE_XPATH = 'small/small'
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
titles = get_titles(doc)
|
18
|
-
dates = get_dates(doc)
|
19
|
-
integrate(titles, dates)
|
15
|
+
def initialize(username)
|
16
|
+
parse_html(username)
|
20
17
|
end
|
21
18
|
|
22
|
-
def
|
23
|
-
|
24
|
-
Nokogiri::HTML(open(url))
|
19
|
+
def badges
|
20
|
+
@badges ||= extract_achievements
|
25
21
|
end
|
26
22
|
|
27
|
-
|
28
|
-
titles = document.xpath(TITLE_XPATH)
|
29
|
-
titles.map { |t| t.text }
|
30
|
-
end
|
23
|
+
private
|
31
24
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
25
|
+
def parse_html(username)
|
26
|
+
url = "#{USERS_URL}/#{username}/#{ACHIEVEMENTS_DIR}"
|
27
|
+
@document = Oga.parse_html(open(url))
|
35
28
|
end
|
36
29
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
30
|
+
def extract_achievements
|
31
|
+
@document.xpath(ACHIEVEMENT_XPATH).map do |achievement|
|
32
|
+
title = achievement.xpath(ACH_TITLE_XPATH).text
|
33
|
+
date = Date.parse(achievement.xpath(ACH_DATE_XPATH).text)
|
34
|
+
[title, date]
|
35
|
+
end.to_h
|
42
36
|
end
|
43
37
|
end
|
44
38
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'oga'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module CodeBadges
|
6
|
+
# This class get the user account as an input
|
7
|
+
# return a hash of user's badges information
|
8
|
+
class CodecademyCourses
|
9
|
+
MAIN_URL = 'https://www.codecademy.com'
|
10
|
+
XPATH_COURSES = "//div[h5/strong/text()='Learn To Code']/div/div/ul/li/a"
|
11
|
+
|
12
|
+
def courses
|
13
|
+
@courses ||= extract_main_courses
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def extract_main_courses
|
19
|
+
doc = Oga.parse_html(open(MAIN_URL))
|
20
|
+
doc.xpath(XPATH_COURSES).map do |course|
|
21
|
+
[course.text, URI.join(MAIN_URL, course.get('href'))]
|
22
|
+
end.to_h
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/codebadges/version.rb
CHANGED
data/lib/codebadges.rb
CHANGED
data/spec/badges_spec.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'minitest/rg'
|
3
|
+
require 'yaml'
|
4
|
+
require 'vcr'
|
5
|
+
require 'webmock/minitest'
|
6
|
+
require './lib/codebadges.rb'
|
7
|
+
|
8
|
+
USERNAME = 'soumya.ray'
|
9
|
+
badges_from_file = YAML.load(File.read('./spec/fixtures/badges.yml'))
|
10
|
+
|
11
|
+
VCR.configure do |config|
|
12
|
+
config.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
13
|
+
config.hook_into :webmock
|
14
|
+
end
|
15
|
+
|
16
|
+
VCR.use_cassette('badges') do
|
17
|
+
badges_found = CodeBadges::CodecademyBadges.new(USERNAME).badges
|
18
|
+
|
19
|
+
describe 'Get badges for one user' do
|
20
|
+
it 'has the right number of badges' do
|
21
|
+
badges_found.size.wont_be :<, badges_from_file[USERNAME].size
|
22
|
+
end
|
23
|
+
|
24
|
+
badges_from_file[USERNAME].map do |b_name, b_date|
|
25
|
+
it "finds '#{b_name}' badge" do
|
26
|
+
badges_found[b_name].must_equal Date.parse(b_date)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'minitest/rg'
|
3
|
+
require 'yaml'
|
4
|
+
require 'vcr'
|
5
|
+
require 'webmock/minitest'
|
6
|
+
require './lib/codebadges.rb'
|
7
|
+
|
8
|
+
test_courses = YAML.load(File.read('spec/fixtures/courses.yml'))
|
9
|
+
|
10
|
+
VCR.configure do |config|
|
11
|
+
config.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
12
|
+
config.hook_into :webmock
|
13
|
+
end
|
14
|
+
|
15
|
+
VCR.use_cassette('courses') do
|
16
|
+
codecademy = CodeBadges::CodecademyCourses.new
|
17
|
+
courses = codecademy.courses
|
18
|
+
|
19
|
+
describe 'Find all test courses' do
|
20
|
+
it 'has the right number of badges' do
|
21
|
+
courses.size.wont_be :<, test_courses.size
|
22
|
+
end
|
23
|
+
|
24
|
+
test_courses.map do |course_name|
|
25
|
+
it "finds course '#{course_name}'" do
|
26
|
+
codecademy.courses.keys.include? course_name
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
---
|
2
|
+
soumya.ray:
|
3
|
+
Sorting Your Friends: May 18, 2014
|
4
|
+
100 Exercises: May 18, 2014
|
5
|
+
Max Streak Count of 3: May 11, 2014
|
6
|
+
Design a Button for Your Website: May 9, 2014
|
7
|
+
'CSS: An Overview': May 9, 2014
|
8
|
+
Build Your Own Webpage: May 9, 2014
|
9
|
+
50 Exercises: May 9, 2014
|
10
|
+
Clickable Photo Page: May 9, 2014
|
11
|
+
HTML Basics III: May 9, 2014
|
12
|
+
25 points earned in one day: May 9, 2014
|
13
|
+
HTML Basics: May 9, 2014
|
14
|
+
25 Exercises: May 9, 2014
|
15
|
+
10 Exercises: Dec 12, 2012
|
16
|
+
Max Streak Count of 1: Dec 12, 2012
|
17
|
+
First Lesson: Jun 20, 2012
|
18
|
+
chenlizhan:
|
19
|
+
Animate Your Name: Sep 26, 2014
|
20
|
+
Banking on Ruby: Aug 25, 2014
|
21
|
+
Object-Oriented Programming II: Aug 25, 2014
|
22
|
+
Virtual Computer: Aug 25, 2014
|
23
|
+
500 Exercises: Aug 25, 2014
|
24
|
+
Object-Oriented Programming I: Aug 22, 2014
|
25
|
+
Blocks, Procs, and Lambdas: Aug 22, 2014
|
26
|
+
The Refactor Factory: Aug 21, 2014
|
27
|
+
The Zen of Ruby: Aug 21, 2014
|
28
|
+
150 points earned in one day: Aug 21, 2014
|
29
|
+
A Night at the Movies: Aug 21, 2014
|
30
|
+
Hashes and Symbols: Aug 21, 2014
|
31
|
+
125 points earned in one day: Aug 21, 2014
|
32
|
+
Ordering Your Library: Aug 21, 2014
|
33
|
+
Methods, Blocks, & Sorting: Aug 21, 2014
|
34
|
+
100 points earned in one day: Aug 21, 2014
|
35
|
+
Create a Histogram: Aug 21, 2014
|
36
|
+
Data Structures: Aug 21, 2014
|
37
|
+
Redacted!: Aug 21, 2014
|
38
|
+
Loops & Iterators: Aug 21, 2014
|
39
|
+
Thith Meanth War!: Aug 21, 2014
|
40
|
+
Control Flow in Ruby: Aug 21, 2014
|
41
|
+
Putting the Form in Formatter: Aug 21, 2014
|
42
|
+
Introduction to Ruby: Aug 21, 2014
|
43
|
+
File Input/Output: Jul 24, 2014
|
44
|
+
Max Streak Count of 5: Jul 24, 2014
|
45
|
+
Classes: Jul 24, 2014
|
46
|
+
Introduction to Classes: Jul 23, 2014
|
47
|
+
Introduction to Bitwise Operators: Jul 22, 2014
|
48
|
+
Advanced Topics in Python: Jul 22, 2014
|
49
|
+
Exam Statistics: Jul 22, 2014
|
50
|
+
Max Streak Count of 3: Jul 22, 2014
|
51
|
+
Practice Makes Perfect: Jul 21, 2014
|
52
|
+
200 Exercises: Jul 21, 2014
|
53
|
+
75 points earned in one day: Jul 21, 2014
|
54
|
+
Loops: Jul 21, 2014
|
55
|
+
Battleship!: Jul 20, 2014
|
56
|
+
Lists and Functions: Jul 20, 2014
|
57
|
+
Student Becomes the Teacher: Jul 20, 2014
|
58
|
+
PygLatin: Jul 20, 2014
|
59
|
+
A Day at the Supermarket: Jul 19, 2014
|
60
|
+
Python Lists and Dictionaries: Jul 19, 2014
|
61
|
+
100 Exercises: Jul 19, 2014
|
62
|
+
Taking a Vacation: Jul 19, 2014
|
63
|
+
Functions: Jul 19, 2014
|
64
|
+
Conditionals & Control Flow: Jul 18, 2014
|
65
|
+
50 points earned in one day: Jul 18, 2014
|
66
|
+
50 Exercises: Jul 18, 2014
|
67
|
+
Date and Time: Jul 18, 2014
|
68
|
+
Strings & Console Output: Jul 18, 2014
|
69
|
+
25 points earned in one day: Jul 18, 2014
|
70
|
+
25 Exercises: Jul 18, 2014
|
71
|
+
Tip Calculator: Jul 18, 2014
|
72
|
+
Python Syntax: Jul 18, 2014
|
73
|
+
First Lesson: Jul 18, 2014
|
74
|
+
10 Exercises: Jul 18, 2014
|
75
|
+
Max Streak Count of 1: Mar 29, 2014
|
@@ -0,0 +1,17 @@
|
|
1
|
+
---
|
2
|
+
- Make a Website
|
3
|
+
- Make a Website Projects
|
4
|
+
- Make an Interactive Website
|
5
|
+
- Learn Rails
|
6
|
+
- Learn AngularJS
|
7
|
+
- Ruby on Rails Authentication
|
8
|
+
- Learn the Command Line
|
9
|
+
- Learn SQL
|
10
|
+
- Learn Java
|
11
|
+
- HTML & CSS
|
12
|
+
- JavaScript
|
13
|
+
- jQuery
|
14
|
+
- PHP
|
15
|
+
- Python
|
16
|
+
- Ruby
|
17
|
+
- Learn APIs
|