kktix_api 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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