kktix_api 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 14b3cd5a1e5bc69df6ab1e32de17b6b5e4b77af7
4
- data.tar.gz: 6f15ff7424af4ca0751e7c6704a61d1a70a272ea
3
+ metadata.gz: 1d273e26139f81b11509b066a991ad7694254715
4
+ data.tar.gz: ee50aaf77c46d5ab5dbae817e31346039dc99b78
5
5
  SHA512:
6
- metadata.gz: 824a0f62dfa70733042af073e431e7e75ea0c83ab8e935efeb7f5d919490c192b840d75b3f1ca201409b6ca50be0697a05cd35710ba3a1621ae1965b31eb9363
7
- data.tar.gz: f5e0a4dd45c252f04933ca124bda5a0849919741248630393a6905f57544c42ffa782531c39bd81ac52ada888eb9707566a27e64689d7ba25bf2947257ed147f
6
+ metadata.gz: e3159983b678d9d7db54d28d580e1fcd812f7d96f89326d9c7490e90d057c897188f3a8c6eb48176bd66ab2c71a9a1b08b82e1e167b63be944068707bef81195
7
+ data.tar.gz: '0589951292caab3e76b66322b2357252dc6080b99e38d929bee7b7a64a4273d98932a95e0e02705d656def4bdb909d490cdd04b87623e7b598857015161f1a29'
data/.gitignore CHANGED
@@ -1,8 +1,7 @@
1
1
  .DS_Store
2
2
 
3
- Gemfile.lock
4
3
  spec/fixtures/
5
4
 
6
5
  coverage/
7
6
 
8
- *.gem
7
+ *.gem
data/Gemfile CHANGED
@@ -2,6 +2,7 @@
2
2
  source 'https://rubygems.org'
3
3
 
4
4
  gem 'http'
5
+ gem 'nokogiri'
5
6
 
6
7
  gem 'minitest'
7
8
  gem 'minitest-rg'
data/Gemfile.lock ADDED
@@ -0,0 +1,89 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ addressable (2.5.0)
5
+ public_suffix (~> 2.0, >= 2.0.2)
6
+ ast (2.3.0)
7
+ crack (0.4.3)
8
+ safe_yaml (~> 1.0.0)
9
+ docile (1.1.5)
10
+ domain_name (0.5.20161129)
11
+ unf (>= 0.0.5, < 1.0.0)
12
+ erubis (2.7.0)
13
+ flay (2.8.1)
14
+ erubis (~> 2.7.0)
15
+ path_expander (~> 1.0)
16
+ ruby_parser (~> 3.0)
17
+ sexp_processor (~> 4.0)
18
+ flog (4.4.0)
19
+ path_expander (~> 1.0)
20
+ ruby_parser (~> 3.1, > 3.1.0)
21
+ sexp_processor (~> 4.4)
22
+ hashdiff (0.3.2)
23
+ http (2.1.0)
24
+ addressable (~> 2.3)
25
+ http-cookie (~> 1.0)
26
+ http-form_data (~> 1.0.1)
27
+ http_parser.rb (~> 0.6.0)
28
+ http-cookie (1.0.3)
29
+ domain_name (~> 0.5)
30
+ http-form_data (1.0.1)
31
+ http_parser.rb (0.6.0)
32
+ json (2.0.2)
33
+ mini_portile2 (2.1.0)
34
+ minitest (5.10.1)
35
+ minitest-rg (5.2.0)
36
+ minitest (~> 5.0)
37
+ nokogiri (1.7.0.1)
38
+ mini_portile2 (~> 2.1.0)
39
+ parser (2.3.3.1)
40
+ ast (~> 2.2)
41
+ path_expander (1.0.1)
42
+ powerpack (0.1.1)
43
+ public_suffix (2.0.5)
44
+ rainbow (2.2.1)
45
+ rake (12.0.0)
46
+ rubocop (0.46.0)
47
+ parser (>= 2.3.1.1, < 3.0)
48
+ powerpack (~> 0.1)
49
+ rainbow (>= 1.99.1, < 3.0)
50
+ ruby-progressbar (~> 1.7)
51
+ unicode-display_width (~> 1.0, >= 1.0.1)
52
+ ruby-progressbar (1.8.1)
53
+ ruby_parser (3.8.3)
54
+ sexp_processor (~> 4.1)
55
+ safe_yaml (1.0.4)
56
+ sexp_processor (4.7.0)
57
+ simplecov (0.12.0)
58
+ docile (~> 1.1.0)
59
+ json (>= 1.8, < 3)
60
+ simplecov-html (~> 0.10.0)
61
+ simplecov-html (0.10.0)
62
+ unf (0.1.4)
63
+ unf_ext
64
+ unf_ext (0.0.7.2)
65
+ unicode-display_width (1.1.2)
66
+ vcr (3.0.3)
67
+ webmock (2.3.2)
68
+ addressable (>= 2.3.6)
69
+ crack (>= 0.3.2)
70
+ hashdiff
71
+
72
+ PLATFORMS
73
+ ruby
74
+
75
+ DEPENDENCIES
76
+ flay
77
+ flog
78
+ http
79
+ minitest
80
+ minitest-rg
81
+ nokogiri
82
+ rake
83
+ rubocop
84
+ simplecov
85
+ vcr
86
+ webmock
87
+
88
+ BUNDLED WITH
89
+ 1.13.6
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
- # kktix_api Gem
1
+ # KKTIX API Gem
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/kktix_api.svg)](https://badge.fury.io/rb/kktix_api)
3
4
  [![Build Status](https://travis-ci.org/twentyfour7/kktix-api.svg?branch=master)](https://travis-ci.org/twentyfour7/kktix-api)
4
5
 
5
- kktix_api is a gem that gets event information of an organization from KKTIX
6
+ kktix_api is a gem that gets event information of an organization from [KKTIX](https://kktix.com)
6
7
 
7
8
  ## Installation
8
9
 
@@ -10,18 +11,48 @@ If you are working on a project, add this to your Gemfile: `gem 'kktix_api'`
10
11
 
11
12
  For ad hoc installation from command line:
12
13
 
13
- ```$ gem install kktix_api```
14
+ ```console
15
+ $ gem install kktix_api
16
+ ```
14
17
 
15
18
 
16
19
  ## Usage
17
20
 
18
- Require kktix_api gem in your code: `require 'kktix_api'`
21
+ Execute `kktix` of an organization with specific `organization_id`; Otherwise, get latest published events.
22
+ ```console
23
+ $ kktix [org_id]
24
+ ```
19
25
 
26
+ ### API
27
+
28
+ Require kktix_api gem in your code:
29
+
30
+ ```ruby
31
+ require 'kktix_api'
32
+ ```
33
+
34
+ Get information using domain class `Organization`, you can get attributes like `name`, `uri`, and all the `events` held by the organization.
35
+
36
+ ```ruby
37
+ organization = KktixEvent::Organization.find('<organization_id>')
38
+ ```
39
+
40
+
41
+ List events information from an `Organization`, including `url`, `published`, `title`,  `summary`, `content`, and `author`.
42
+
43
+ ```ruby
44
+ organization.events.each do |event|
45
+  puts "#{event.title} (#{event.published})"
46
+ puts event.url
47
+ puts event.content
48
+  puts
49
+ end
50
+ ```
20
51
 
21
52
  See the following example code for more usage details:
22
53
 
23
54
  ```ruby
24
- oid = '<your organization id>'
55
+ oid = 'nthuion'
25
56
 
26
57
  acts = KktixEvent::KktixApi.events(oid)
27
58
  puts acts
@@ -32,4 +63,4 @@ organization.events.each do |event|
32
63
  puts event.title, event.published
33
64
  end
34
65
 
35
- ```
66
+ ```
data/Rakefile CHANGED
@@ -1,16 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
  require 'rake/testtask'
3
3
 
4
- task default: :spec
5
-
6
- # desc 'Run specs'
7
- # Rake::TestTask.new(name=:spec) do |t|
8
- # t.pattern = 'spec/*_spec.rb'
9
- # end
4
+ task :default do
5
+ puts `rake -T`
6
+ end
10
7
 
11
- desc 'run tests'
12
- task :spec do
13
- sh 'ruby spec/kktix_spec.rb'
8
+ desc 'run specs'
9
+ Rake::TestTask.new(:spec) do |t|
10
+ t.pattern = 'spec/*_spec.rb'
11
+ t.warning = false
14
12
  end
15
13
 
16
14
  desc 'delete cassette fixtures'
data/bin/kktix CHANGED
@@ -3,22 +3,19 @@
3
3
  $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
4
  require 'kktix_api'
5
5
 
6
- org_id = ARGV[0] || ENV['KKTIX_ORGANIZATION_ID']
7
- # unless org_id
8
- # puts 'USAGE: kktix [org_id]'
9
- # exit(1)
10
- # end
11
-
12
- organization = KktixEvent::Organization.find(org_id)
13
-
14
- unless organization.name.nil?
15
- puts organization.name
16
- puts '-' * organization.name.length
6
+ keyword = ARGV[0]
7
+ unless keyword
8
+ puts 'USAGE: kktix [keyword]'
9
+ exit(1)
17
10
  end
18
11
 
19
- organization.events.first(3).each.with_index(1) do |event, index|
12
+ puts "Search for #{keyword}..."
13
+ events = KktixEvent::Event.search(keyword)
14
+
15
+ events.first(10).each.with_index(1) do |event, index|
20
16
  print "#{index}: "
21
- puts "#{event.title} (#{event.published})"
22
- puts event.summary ? event.summary : event.content
17
+ puts "#{event.title} (#{event.author[:name]})"
18
+ puts event.summary
19
+ puts event.content
23
20
  puts
24
21
  end
data/kktix_api.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.executables << 'kktix'
17
17
 
18
18
  s.add_runtime_dependency 'http', '~> 2.0'
19
+ s.add_runtime_dependency 'nokogiri', '~> 1.7'
19
20
 
20
21
  s.add_development_dependency 'minitest', '~> 5.9'
21
22
  s.add_development_dependency 'minitest-rg', '~> 5.2'
@@ -4,21 +4,28 @@ require_relative 'kktix_api'
4
4
  module KktixEvent
5
5
  # Single event on organiztion's feed
6
6
  class Event
7
- attr_reader :url, :published, :title, :summary, :content, :author
7
+ attr_reader :url, :title, :summary, :content, :author
8
8
 
9
9
  def initialize(event_data)
10
10
  load_data(event_data)
11
11
  end
12
12
 
13
+ def self.search(query)
14
+ events_hash = KktixApi.search(query)
15
+ events = events_hash.map do |event_hash|
16
+ new(event_hash)
17
+ end
18
+ events
19
+ end
20
+
13
21
  private
14
22
 
15
23
  def load_data(event_data)
16
- @url = event_data['url']
17
- @published = event_data['published']
18
- @title = event_data['title']
19
- @summary = event_data['summary']
20
- @content = event_data['content']
21
- @author = event_data['author']
24
+ @url = event_data[:url]
25
+ @title = event_data[:title]
26
+ @summary = event_data[:summary]
27
+ @content = event_data[:content]
28
+ @author = event_data[:author]
22
29
  end
23
30
  end
24
31
  end
@@ -1,19 +1,68 @@
1
1
  # frozen_string_literal: true
2
2
  require 'yaml'
3
3
  require 'http'
4
+ require 'open-uri'
5
+ require 'nokogiri'
6
+ require 'uri'
7
+ require 'date'
4
8
 
5
9
  module KktixEvent
6
10
  # Service for retriving KKTIX events
7
11
  class KktixApi
8
- def self.events(oid = nil)
9
- response = HTTP.get(events_json_uri(oid: oid)).parse
10
- return response['entry'] if response.key?('entry')
12
+ def self.events(slug: nil)
13
+ response = HTTP.get(events_json_uri(slug: slug)).parse
14
+ return hash_s_to_sym(response['entry']) if response.key?('entry')
11
15
  []
12
16
  end
13
17
 
14
- def self.events_json_uri(oid: nil)
15
- return 'https://kktix.com/events.json' if oid.nil?
16
- "http://#{oid}.kktix.cc/events.json"
18
+ def self.search(query, start_at: Date.today)
19
+ start_at = start_at.to_s
20
+ uri = URI.escape("https://kktix.com/events?start_at=#{start_at}&search=#{query}")
21
+ doc = Nokogiri::HTML(open(uri))
22
+ parse_search_result(doc)
23
+ end
24
+
25
+ def self.events_json_uri(slug: nil)
26
+ return 'https://kktix.com/events.json' if slug.nil?
27
+ "http://#{slug}.kktix.cc/events.json"
28
+ end
29
+
30
+ private_class_method
31
+
32
+ def self.hash_s_to_sym(obj)
33
+ return obj.map { |hash| hash_s_to_sym(hash) } if obj.class == Array
34
+ obj.each_with_object({}) do |(k, v), memo|
35
+ # if v.class == Array
36
+ v = hash_s_to_sym(v) if v.class == Hash
37
+ memo[k.to_sym] = v
38
+ memo
39
+ end
40
+ end
41
+
42
+ def self.parse_search_result(doc)
43
+ events = doc.css('ul.event-list > li').map do |node|
44
+ title, url = parse_title node
45
+ date = node.css('.date').text
46
+ author = parse_author(node)
47
+ summary = node.css('> .description').text
48
+
49
+ { url: url, title: title, date: date, summary: summary, author: author }
50
+ end
51
+ events
52
+ end
53
+
54
+ def self.parse_title(node)
55
+ title_node = node.css('> h2 > a')
56
+ title = title_node.text.strip
57
+ url = title_node.attr('href').value
58
+ [title, url]
59
+ end
60
+
61
+ def self.parse_author(node)
62
+ author_node = node.css('.host')
63
+ name = author_node.text.strip
64
+ uri = author_node.css('> a').attr('href').value
65
+ { name: name, uri: uri }
17
66
  end
18
67
  end
19
68
  end
@@ -5,28 +5,28 @@ require_relative 'event'
5
5
  module KktixEvent
6
6
  # Single organization on KKTIX
7
7
  class Organization
8
- attr_reader :oid, :name, :uri, :events
8
+ attr_reader :slug, :name, :uri, :events
9
9
 
10
- def initialize(organization_data, oid: nil)
11
- update_info(organization_data, oid)
10
+ def initialize(organization_data, slug: nil)
11
+ update_info(organization_data, slug)
12
12
  end
13
13
 
14
- def self.find(oid = nil)
15
- organization_data = KktixEvent::KktixApi.events(oid)
16
- new(organization_data, oid: oid)
14
+ def self.find(slug = nil)
15
+ events = KktixEvent::KktixApi.events(slug: slug)
16
+ new(events, slug: slug)
17
17
  end
18
18
 
19
19
  private
20
20
 
21
- def update_info(entry, oid)
22
- unless oid.nil?
23
- author = entry.first['author']
24
- @oid = oid
25
- @name = author['name']
26
- @uri = author['uri']
21
+ def update_info(events, slug)
22
+ unless slug.nil?
23
+ author = events.first[:author]
24
+ @slug = slug
25
+ @name = author[:name]
26
+ @uri = author[:uri]
27
27
  end
28
- @events = entry.map do |event_data|
29
- KktixEvent::Event.new(event_data)
28
+ @events = events.map do |event_data|
29
+ Event.new(event_data)
30
30
  end
31
31
  end
32
32
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KktixEvent
4
+ VERSION = '1.0.0'
5
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'spec_helper.rb'
3
+
4
+ describe 'Event spec' do
5
+ VCR.configure do |c|
6
+ c.cassette_library_dir = CASSETTES_FOLDER
7
+ c.hook_into :webmock
8
+ end
9
+
10
+ before do
11
+ VCR.insert_cassette CASSETTE_FILE, record: :new_episodes
12
+ @organization = KktixEvent::Organization.find(TEST_ORG_SLUG)
13
+ end
14
+
15
+ after do
16
+ VCR.eject_cassette
17
+ end
18
+
19
+ it 'should be able to search events throuh api' do
20
+ KktixEvent::Event.search('go').wont_be_empty
21
+ end
22
+ end
data/spec/kktix_spec.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'spec_helper.rb'
3
3
 
4
- describe 'KKTIX API spec' do
4
+ describe 'KKTIX API get events spec' do
5
5
  VCR.configure do |c|
6
6
  c.cassette_library_dir = CASSETTES_FOLDER
7
7
  c.hook_into :webmock
@@ -20,38 +20,10 @@ describe 'KKTIX API spec' do
20
20
  end
21
21
 
22
22
  it 'should be able to return an empty array if the org does not exist' do
23
- KktixEvent::KktixApi.events('notexist').empty?
24
- end
25
- end
26
-
27
- describe 'KKTIX API spec' do
28
- VCR.configure do |c|
29
- c.cassette_library_dir = CASSETTES_FOLDER
30
- c.hook_into :webmock
31
- end
32
-
33
- before do
34
- VCR.insert_cassette CASSETTE_FILE, record: :new_episodes
35
- @organization = KktixEvent::Organization.find(TEST_ORG_ID)
36
- end
37
-
38
- after do
39
- VCR.eject_cassette
40
- end
41
-
42
- it 'should be the same oid of the organization' do
43
- @organization.oid.must_equal TEST_ORG_ID
44
- end
45
-
46
- it 'should be able to get name of the organization' do
47
- @organization.name.length.must_be :>, 0
48
- end
49
-
50
- it 'should be able to get uri of the organization' do
51
- @organization.uri.length.must_be :>, 0
23
+ KktixEvent::KktixApi.events(slug: 'notexist').empty?
52
24
  end
53
25
 
54
- it 'should be able to get events the organization' do
55
- @organization.events.wont_be_empty
26
+ it 'should be able to search events throuh api' do
27
+ KktixEvent::KktixApi.search('go').wont_be_empty
56
28
  end
57
29
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'spec_helper.rb'
3
+
4
+ describe 'Organization spec' do
5
+ VCR.configure do |c|
6
+ c.cassette_library_dir = CASSETTES_FOLDER
7
+ c.hook_into :webmock
8
+ end
9
+
10
+ before do
11
+ VCR.insert_cassette CASSETTE_FILE, record: :new_episodes
12
+ @organization = KktixEvent::Organization.find(TEST_ORG_SLUG)
13
+ end
14
+
15
+ after do
16
+ VCR.eject_cassette
17
+ end
18
+
19
+ it 'should be the same oid of the organization' do
20
+ @organization.slug.must_equal TEST_ORG_SLUG
21
+ end
22
+
23
+ it 'should be able to get name of the organization' do
24
+ @organization.name.length.must_be :>, 0
25
+ end
26
+
27
+ it 'should be able to get uri of the organization' do
28
+ @organization.uri.length.must_be :>, 0
29
+ end
30
+
31
+ it 'should be able to get events the organization' do
32
+ @organization.events.wont_be_empty
33
+ end
34
+ end
data/spec/spec_helper.rb CHANGED
@@ -14,6 +14,6 @@ FIXTURES_FOLDER = 'spec/fixtures'
14
14
  CASSETTES_FOLDER = "#{FIXTURES_FOLDER}/cassettes"
15
15
  CASSETTE_FILE = 'kktix_api'
16
16
 
17
- TEST_ORG_ID = 'nthuion'
17
+ TEST_ORG_SLUG = 'nthuion'
18
18
  # KKTIX_RESPONSE = YAML.load(File.read('spec/fixtures/kktix_response.yml'))
19
19
  # TEST_ORG_INFO = YAML.load(File.read('spec/fixtures/nthuion_info.yml'))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kktix_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JJC
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-10-30 00:00:00.000000000 Z
13
+ date: 2017-01-07 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: http
@@ -26,6 +26,20 @@ dependencies:
26
26
  - - "~>"
27
27
  - !ruby/object:Gem::Version
28
28
  version: '2.0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: nokogiri
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: '1.7'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: '1.7'
29
43
  - !ruby/object:Gem::Dependency
30
44
  name: minitest
31
45
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +178,7 @@ files:
164
178
  - ".rubocop.yml"
165
179
  - ".travis.yml"
166
180
  - Gemfile
181
+ - Gemfile.lock
167
182
  - LICENSE
168
183
  - README.md
169
184
  - Rakefile
@@ -172,9 +187,12 @@ files:
172
187
  - lib/kktix-api/event.rb
173
188
  - lib/kktix-api/kktix_api.rb
174
189
  - lib/kktix-api/organization.rb
190
+ - lib/kktix-api/version.rb
175
191
  - lib/kktix_api.rb
176
192
  - lib/test.rb
193
+ - spec/event_spec.rb
177
194
  - spec/kktix_spec.rb
195
+ - spec/organization_spec.rb
178
196
  - spec/spec_helper.rb
179
197
  homepage: https://github.com/twentyfour7/kktix-api
180
198
  licenses:
@@ -196,10 +214,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
214
  version: '0'
197
215
  requirements: []
198
216
  rubyforge_project:
199
- rubygems_version: 2.5.1
217
+ rubygems_version: 2.6.8
200
218
  signing_key:
201
219
  specification_version: 4
202
220
  summary: Gets event content of an organization from KKTIX
203
221
  test_files:
222
+ - spec/event_spec.rb
204
223
  - spec/kktix_spec.rb
224
+ - spec/organization_spec.rb
205
225
  - spec/spec_helper.rb