picturehouse_uk 4.0.0 → 5.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.
Files changed (53) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +26 -0
  3. data/.github/workflows/release.yml +26 -0
  4. data/.gitignore +1 -0
  5. data/.ruby-version +1 -0
  6. data/CHANGELOG.md +25 -0
  7. data/Rakefile +2 -2
  8. data/lib/picturehouse_uk/cinema.rb +30 -14
  9. data/lib/picturehouse_uk/internal/api.rb +42 -0
  10. data/lib/picturehouse_uk/internal/parser/address.rb +21 -6
  11. data/lib/picturehouse_uk/internal/parser/screenings.rb +85 -133
  12. data/lib/picturehouse_uk/internal/website.rb +10 -12
  13. data/lib/picturehouse_uk/version.rb +2 -2
  14. data/lib/picturehouse_uk.rb +1 -0
  15. data/picturehouse_uk.gemspec +2 -3
  16. data/rake/fixture_creator.rb +21 -1
  17. data/test/fixtures/cinemas.html +4262 -0
  18. data/test/fixtures/duke-of-york-s-picturehouse/cinema.html +6187 -0
  19. data/test/fixtures/duke-of-york-s-picturehouse/get_movies.json +120552 -0
  20. data/test/fixtures/duke-of-york-s-picturehouse/information.html +3725 -0
  21. data/test/fixtures/duke-s-at-komedia/cinema.html +6138 -0
  22. data/test/fixtures/duke-s-at-komedia/get_movies.json +112 -0
  23. data/test/fixtures/duke-s-at-komedia/information.html +3690 -0
  24. data/test/fixtures/home.html +6235 -555
  25. data/test/fixtures/phoenix-picturehouse/cinema.html +6089 -0
  26. data/test/fixtures/phoenix-picturehouse/get_movies.json +120552 -0
  27. data/test/fixtures/phoenix-picturehouse/information.html +3630 -0
  28. data/test/lib/picturehouse_uk/cinema_test.rb +34 -34
  29. data/test/lib/picturehouse_uk/internal/api_test.rb +92 -0
  30. data/test/lib/picturehouse_uk/internal/parser/address_test.rb +8 -8
  31. data/test/lib/picturehouse_uk/internal/parser/screenings_test.rb +99 -45
  32. data/test/lib/picturehouse_uk/internal/title_sanitizer_test.rb +48 -48
  33. data/test/lib/picturehouse_uk/internal/website_test.rb +12 -31
  34. data/test/lib/picturehouse_uk/performance_test.rb +63 -23
  35. data/test/lib/picturehouse_uk/version_test.rb +1 -1
  36. data/test/live/integration_test.rb +8 -8
  37. data/test/support/fake_api.rb +16 -0
  38. data/test/support/fake_website.rb +6 -6
  39. data/test/test_helper.rb +3 -2
  40. metadata +34 -50
  41. data/.travis.yml +0 -8
  42. data/test/fixtures/Duke_Of_Yorks/cinema.html +0 -3408
  43. data/test/fixtures/Duke_Of_Yorks/info.html +0 -556
  44. data/test/fixtures/Duke_Of_Yorks/whats_on.html +0 -3159
  45. data/test/fixtures/Dukes_At_Komedia/cinema.html +0 -4764
  46. data/test/fixtures/Dukes_At_Komedia/info.html +0 -526
  47. data/test/fixtures/Dukes_At_Komedia/whats_on.html +0 -4429
  48. data/test/fixtures/National_Media_Museum/cinema.html +0 -9200
  49. data/test/fixtures/National_Media_Museum/info.html +0 -606
  50. data/test/fixtures/National_Media_Museum/whats_on.html +0 -8850
  51. data/test/fixtures/Phoenix_Picturehouse/cinema.html +0 -8274
  52. data/test/fixtures/Phoenix_Picturehouse/info.html +0 -542
  53. data/test/fixtures/Phoenix_Picturehouse/whats_on.html +0 -7986
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cb14c9688f95477661a9dae62733b969a842bd60
4
- data.tar.gz: 68b02405cb818334fa91d1a85355ea342517c08b
2
+ SHA256:
3
+ metadata.gz: 5c4c71062363f2efdabda5696692051f79c7915f250367ff8c16536e058c821b
4
+ data.tar.gz: a76bf492b267b7ae89cbbe829b4269dea9ac0207add6b41fe47685d1df76fbb9
5
5
  SHA512:
6
- metadata.gz: 6d127befd1075646556a86f7579a4c3f00d84f45dc84902dedec6728881aaa4daafb0d1a3164706ae1417b2bd1f90b582cecf6e2263c4e3446d5dacfb4ff82f4
7
- data.tar.gz: c9030d13d6db43f2ec2b1a8aeded059bd54d81f7678887a60b3ba9241baa3cf35f39f6294224b2e36af6ab0fcb9de711369a35d37ddb913e39d764a59a6ab719
6
+ metadata.gz: b1722850d1b2f161725a961f420b8122c404161050c794b02d93a8f735c5d7053745c2eb35de8d0200e5cc20cd2525024ed94a4cc63357fe2157fc9e149fdc11
7
+ data.tar.gz: d5225d4815b31cd31d072820f55e257e72cc415e619c8cbb3eaa6b5c7609d81b624107554d367036164f07da58d83bc5656d5e0ad42df154d955af02411d06fd
@@ -0,0 +1,26 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: '3.4'
20
+ bundler-cache: true
21
+
22
+ - name: Run tests
23
+ run: bundle exec rake
24
+
25
+ - name: Run live tests
26
+ run: bundle exec rake live
@@ -0,0 +1,26 @@
1
+ name: Release Gem
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ jobs:
7
+ release:
8
+ runs-on: ubuntu-latest
9
+ permissions:
10
+ id-token: write
11
+ contents: write
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: '3.4'
20
+ bundler-cache: true
21
+
22
+ - name: Run tests
23
+ run: bundle exec rake test
24
+
25
+ - name: Release gem
26
+ uses: rubygems/release-gem@v1
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ vendor/*
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4.7
data/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
+ ## [5.0.0] - 2025-10-31
6
+
7
+ ### Added
8
+ - JSON API client for fetching performance data from `/api/get-movies-ajax` endpoint
9
+ - `PicturehouseUk::Internal::Api` for making API requests
10
+ - `PicturehouseUk::Internal::Parser::Screenings` for parsing JSON responses (replaced old HTML parser)
11
+ - Comprehensive tests for JSON API functionality
12
+ - Sample JSON fixtures for testing
13
+
14
+ ### Changed
15
+ - `Performance.at()` now uses JSON API instead of HTML parsing
16
+ - Improved variant detection (arts, baby, kids, senior, imax)
17
+ - Booking URLs now use Vista format: `https://web.picturehouses.com/order/showtimes/{cinema_id}-{session_id}/seats`
18
+ - Enhanced 3D film detection from both title and attributes
19
+ - Increased test coverage to 98.65%
20
+
21
+ ### Removed
22
+ - Old HTML parser `Parser::Screenings` (completely replaced with JSON API version)
23
+ - Test file for old HTML parser
24
+
25
+ ### Technical Details
26
+ - The Picturehouse website now dynamically populates screening data via AJAX calls to their JSON API
27
+ - The `#show_all_date_list` div is populated client-side with data from the API endpoint
28
+ - HTML parsing approach replaced with direct API consumption for better reliability
29
+
5
30
  ## 4.0.0 - 2016-02-10
6
31
 
7
32
  The cinebase standardisation release.
data/Rakefile CHANGED
@@ -37,8 +37,8 @@ task :fixtures do
37
37
  require_relative 'rake/fixture_creator'
38
38
 
39
39
  FixtureCreator.new.home
40
- %w(Duke_Of_Yorks Dukes_At_Komedia Phoenix_Picturehouse
41
- National_Media_Museum).each do |cinema_id|
40
+ FixtureCreator.new.cinemas
41
+ %w(duke-of-york-s-picturehouse duke-s-at-komedia phoenix-picturehouse).each do |cinema_id|
42
42
  FixtureCreator.new.cinema(cinema_id)
43
43
  end
44
44
  end
@@ -2,9 +2,9 @@ module PicturehouseUk
2
2
  # The object representing a cinema on the Picturehouse UK website
3
3
  class Cinema < Cinebase::Cinema
4
4
  # address css
5
- ADDRESS_CSS = '.static-content #contact-us + p:first'.freeze
6
- # cinema link css
7
- CINEMA_LINKS_CSS = '.footer .col-sm-3 option + option'.freeze
5
+ ADDRESS_CSS = '.cinemaAdrass:not(.openingTime)'.freeze
6
+ # cinema link css on the /cinema page
7
+ CINEMA_LINKS_CSS = 'a[href*="/cinema/"]'.freeze
8
8
 
9
9
  # @!attribute [r] id
10
10
  # @return [Integer] the numeric id of the cinema on the Cineworld website
@@ -147,15 +147,15 @@ module PicturehouseUk
147
147
  private
148
148
 
149
149
  def self.cinema_links
150
- home_doc.css(CINEMA_LINKS_CSS)
150
+ cinemas_doc.css(CINEMA_LINKS_CSS)
151
151
  end
152
152
  private_class_method :cinema_links
153
153
 
154
- def self.home_doc
155
- @home_doc ||=
156
- Nokogiri::HTML(PicturehouseUk::Internal::Website.new.home)
154
+ def self.cinemas_doc
155
+ @cinemas_doc ||=
156
+ Nokogiri::HTML(PicturehouseUk::Internal::Website.new.cinemas)
157
157
  end
158
- private_class_method :home_doc
158
+ private_class_method :cinemas_doc
159
159
 
160
160
  def address_node
161
161
  @address_node ||= info_doc.css(ADDRESS_CSS)
@@ -163,11 +163,11 @@ module PicturehouseUk
163
163
 
164
164
  def info_doc
165
165
  @info_doc ||=
166
- Nokogiri::HTML(PicturehouseUk::Internal::Website.new.info(id))
166
+ Nokogiri::HTML(PicturehouseUk::Internal::Website.new.information(id))
167
167
  end
168
168
 
169
169
  # @api private
170
- # Utility class to parse the links spat out from the options
170
+ # Utility class to parse the links from the cinemas page
171
171
  class ListParser
172
172
  def initialize(nodes)
173
173
  @nodes = nodes
@@ -175,22 +175,38 @@ module PicturehouseUk
175
175
 
176
176
  def to_hash
177
177
  @nodes.each_with_object({}) do |node, result|
178
- result[id(node)] = { name: name(node), url: url(node) }
178
+ cinema_id = id(node)
179
+ cinema_name = name(node)
180
+ # Skip links that don't have valid cinema data
181
+ next unless cinema_id && cinema_name
182
+ # Skip duplicate entries
183
+ next if result.key?(cinema_id)
184
+
185
+ result[cinema_id] = { name: cinema_name, url: url(node) }
179
186
  end
180
187
  end
181
188
 
182
189
  private
183
190
 
184
191
  def id(node)
185
- url(node).match(%r{/cinema/(.+)$})[1]
192
+ href = url(node)
193
+ return nil unless href
194
+ match = href.match(%r{/cinema/([^/?#]+)})
195
+ match ? match[1] : nil
186
196
  end
187
197
 
188
198
  def name(node)
189
- node.children.first.to_s.split(' ')[1]
199
+ # Cinema name is in a <p> tag within the link
200
+ p_tag = node.css('p').first
201
+ return nil unless p_tag
202
+ # Get text and remove the location span
203
+ p_tag.children.find { |child| child.text? }&.text&.strip
190
204
  end
191
205
 
192
206
  def url(node)
193
- node.get_attribute('data-href')
207
+ href = node.get_attribute('href')
208
+ # Convert relative URLs to absolute if needed
209
+ href&.start_with?('http') ? href : "https://www.picturehouses.com#{href}"
194
210
  end
195
211
  end
196
212
  end
@@ -0,0 +1,42 @@
1
+ require 'net/http'
2
+ require 'json'
3
+ require 'openssl'
4
+
5
+ module PicturehouseUk
6
+ # @api private
7
+ module Internal
8
+ # Fetches JSON data from the Picturehouse API
9
+ class Api
10
+ API_BASE = 'https://www.picturehouses.com'.freeze
11
+ API_ENDPOINT = '/api/get-movies-ajax'.freeze
12
+
13
+ # Fetch movie data for a cinema
14
+ # @param cinema_id [String] the cinema ID
15
+ # @param date [String] the date in YYYY-MM-DD format, or 'show_all_dates'
16
+ # @return [Hash] parsed JSON response
17
+ def get_movies(cinema_id, date = 'show_all_dates')
18
+ uri = URI("#{API_BASE}#{API_ENDPOINT}")
19
+
20
+ http = Net::HTTP.new(uri.host, uri.port)
21
+ http.use_ssl = true
22
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
23
+
24
+ request = Net::HTTP::Post.new(uri.path)
25
+ request.set_form_data(
26
+ 'start_date' => date,
27
+ 'cinema_id' => cinema_id,
28
+ 'filters' => []
29
+ )
30
+
31
+ response = http.request(request)
32
+
33
+ return {} unless response.is_a?(Net::HTTPSuccess)
34
+
35
+ JSON.parse(response.body)
36
+ rescue StandardError => e
37
+ warn "Failed to fetch movies for cinema #{cinema_id}: #{e.message}"
38
+ {}
39
+ end
40
+ end
41
+ end
42
+ end
@@ -15,7 +15,7 @@ module PicturehouseUk
15
15
  # @note Uses the address naming from http://microformats.org/wiki/adr
16
16
  def address
17
17
  {
18
- street_address: array[1],
18
+ street_address: address_lines[0],
19
19
  extended_address: extended_address,
20
20
  locality: town,
21
21
  region: region,
@@ -27,23 +27,38 @@ module PicturehouseUk
27
27
  private
28
28
 
29
29
  def array
30
- @array ||= Array(@html.gsub(/\<.?p.?\>/, '').split('<br>'))
30
+ @array ||= begin
31
+ # Split on <br> tags first, then strip all HTML tags from each part
32
+ @html.split(/<br\s*\/?>/).map do |part|
33
+ # Strip all HTML tags and clean up whitespace
34
+ Nokogiri::HTML::DocumentFragment.parse(part).text.strip
35
+ end.reject(&:empty?)
36
+ end
37
+ end
38
+
39
+ # Skip the first element (cinema name) and return address lines
40
+ def address_lines
41
+ @address_lines ||= array[1..-1] || []
31
42
  end
32
43
 
33
44
  def extended_address
34
- array.length > 5 ? array[2] : nil
45
+ address_lines.length > 4 ? address_lines[1] : nil
35
46
  end
36
47
 
37
48
  def postal_code
38
- array[-1]
49
+ address_lines[-1]
39
50
  end
40
51
 
41
52
  def region
42
- array[-2] == town ? nil : array[-2]
53
+ # If there are 4+ address lines (street, town, region, postcode),
54
+ # the region is at -2, otherwise nil
55
+ address_lines.length >= 4 ? address_lines[-2] : nil
43
56
  end
44
57
 
45
58
  def town
46
- @town ||= array[0].to_s.split(', ')[-1]
59
+ # Town is always the second-to-last item (before postcode)
60
+ # unless there's a region, then it's third-to-last
61
+ @town ||= address_lines.length >= 4 ? address_lines[-3] : address_lines[-2]
47
62
  end
48
63
  end
49
64
  end
@@ -3,170 +3,122 @@ module PicturehouseUk
3
3
  module Internal
4
4
  # @api private
5
5
  module Parser
6
- # Parses screenings page into an array of hashes for an individual cinema
6
+ # Parses JSON API response into an array of screening hashes
7
7
  class Screenings
8
- # css for a day of films & screenings
9
- LISTINGS = '.listings li:not(.dark)'.freeze
10
- DATE = '.nav-collapse.collapse'.freeze
11
-
12
8
  def initialize(cinema_id)
13
9
  @cinema_id = cinema_id
14
10
  end
15
11
 
16
- # parse the cinema page into an array of screenings attributes
12
+ # Parse the JSON response into an array of screening attributes
17
13
  # @return [Array<Hash>]
18
14
  def to_a
19
- doc.css(LISTINGS).flat_map do |node|
20
- FilmWithShowtimes.new(node,
21
- date_from_html(node.css(DATE).to_s)).to_a
22
- end
15
+ return [] unless json_data['response'] == 'success'
16
+ return [] unless json_data['movies']
17
+
18
+ json_data['movies'].flat_map do |movie|
19
+ parse_movie(movie)
20
+ end.compact
23
21
  end
24
22
 
25
23
  private
26
24
 
27
- def date_from_html(html)
28
- if html =~ /listings-further-ahead-today/
29
- Date.now
30
- else
31
- html.match(/listings-further-ahead-(\d{4})(\d{2})(\d{2})/) do |m|
32
- Date.new(m[1].to_i, m[2].to_i, m[3].to_i)
33
- end
34
- end
35
- end
25
+ def parse_movie(movie)
26
+ return [] if movie['show_times'].nil? || movie['show_times'].empty?
36
27
 
37
- def doc
38
- @doc ||= Nokogiri::HTML(page)
28
+ movie['show_times'].map do |timing|
29
+ parse_timing(movie, timing)
30
+ end.compact
39
31
  end
40
32
 
41
- def page
42
- @page ||= PicturehouseUk::Internal::Website.new.whats_on(@cinema_id)
43
- end
44
- end
45
- end
46
-
47
- # @api private
48
- # collection of timings for a specific film
49
- class FilmWithShowtimes
50
- # film name css
51
- NAME = '.top-mg-sm a'.freeze
52
- # variants css
53
- VARIANTS = '.film-times .col-xs-10'.freeze
54
-
55
- def initialize(node, date)
56
- @node = node
57
- @date = date
58
- end
59
-
60
- # The film name
61
- # @return [String]
62
- def name
63
- TitleSanitizer.new(raw_name).sanitized
64
- end
33
+ def parse_timing(movie, timing)
34
+ # Skip sold out or unavailable screenings
35
+ return nil if timing['SoldoutStatus'] == 2
36
+ return nil unless timing['date_f'] && timing['time']
65
37
 
66
- # Showings hashes
67
- # @return [Array<Hash>]
68
- def to_a
69
- Array(@node.css(VARIANTS)).flat_map do |variant|
70
- Variant.new(variant, @date).to_a.map do |hash|
71
- {
72
- film_name: name,
73
- dimension: dimension
74
- }.merge(hash)
38
+ # Skip advance booking restrictions if not advertised
39
+ if movie['ABgtToday'] == true && movie['AdvertiseAdvanceBookingDate'] == false
40
+ return nil
75
41
  end
76
- end
77
- end
78
-
79
- private
80
42
 
81
- def dimension
82
- raw_name =~ /3d/i ? '3d' : '2d'
83
- end
84
-
85
- def raw_name
86
- @raw_name ||= @node.css(NAME).children.first.to_s
87
- end
88
- end
89
-
90
- # @api private
91
- # variants can have multiple screenings
92
- class Variant
93
- SHOWTIMES = '.btn'.freeze
94
- VARIANT = '.film-type-desc'.freeze
95
- TRANSLATOR = {
96
- 'Big Scream' => 'baby',
97
- 'IMAX' => 'imax',
98
- "Kids' Club" => 'kids',
99
- 'NT Live' => 'arts',
100
- 'Screen Arts' => 'arts',
101
- 'Silver Screen' => 'senior'
102
- }.freeze
103
-
104
- def initialize(node, date)
105
- @node = node
106
- @date = date
107
- end
43
+ {
44
+ film_name: sanitize_title(movie['Title']),
45
+ dimension: determine_dimension(movie['Title'], timing),
46
+ variant: extract_variants(timing),
47
+ booking_url: booking_url(timing),
48
+ starting_at: parse_datetime(timing['date_f'], timing['time'])
49
+ }
50
+ end
108
51
 
109
- # Variant arrays
110
- # @return [Array<Hash>]
111
- def to_a
112
- @node.css(SHOWTIMES).map do |node|
113
- { variant: variant }.merge(Showtime.new(@node, @date).to_hash)
52
+ def sanitize_title(title)
53
+ TitleSanitizer.new(title).sanitized
114
54
  end
115
- end
116
55
 
117
- private
56
+ def determine_dimension(title, timing)
57
+ # Check title for 3D indicator
58
+ return '3d' if title =~ /3d/i
118
59
 
119
- def variant
120
- @variant ||= TRANSLATOR.select do |k, _|
121
- variant_text.include?(k)
122
- end.values.uniq
123
- end
60
+ # Check timing attributes for 3D
61
+ if timing['SessionAttributesNames']
62
+ return '3d' if timing['SessionAttributesNames'].any? { |attr| attr =~ /3d/i }
63
+ end
124
64
 
125
- def variant_text
126
- @variant_text ||= @node.css(VARIANT).to_s
127
- end
128
- end
65
+ '2d'
66
+ end
129
67
 
130
- # @api private
131
- # parse an individual screening node
132
- class Showtime
133
- def initialize(node, date)
134
- @node = node
135
- @date = date
136
- end
68
+ def extract_variants(timing)
69
+ return [] unless timing['SessionAttributesNames']
137
70
 
138
- def to_hash
139
- {
140
- booking_url: booking_url,
141
- starting_at: starting_at
142
- }
143
- end
71
+ variants = []
144
72
 
145
- private
73
+ timing['SessionAttributesNames'].each do |attribute|
74
+ # Map known attributes to variant types
75
+ variants << 'baby' if attribute =~ /big scream/i
76
+ variants << 'imax' if attribute =~ /imax/i
77
+ variants << 'kids' if attribute =~ /kids|toddler/i
78
+ variants << 'arts' if attribute =~ /nt live|screen arts|rbo|roh|met opera/i
79
+ variants << 'senior' if attribute =~ /silver screen/i
80
+ end
146
81
 
147
- def booking_url
148
- return if href.nil? || href.empty?
149
- "https://picturehouses.com#{href}"
150
- end
82
+ variants.uniq.sort
83
+ end
151
84
 
152
- def hour
153
- split[0]
154
- end
85
+ def booking_url(timing)
86
+ return nil unless timing['SessionId']
155
87
 
156
- def href
157
- @href ||= @node['href']
158
- end
88
+ # Vista booking URL format
89
+ "https://web.picturehouses.com/order/showtimes/#{@cinema_id}-#{timing['SessionId']}/seats"
90
+ end
159
91
 
160
- def min
161
- split[1]
162
- end
92
+ def parse_datetime(date_str, time_str)
93
+ # date_str format: "2024-10-30"
94
+ # time_str format: "19:30"
95
+ return nil unless date_str && time_str
96
+
97
+ date_parts = date_str.split('-').map(&:to_i)
98
+ time_parts = time_str.split(':').map(&:to_i)
99
+
100
+ # Create Time object in local timezone, then convert to UTC
101
+ Time.new(
102
+ date_parts[0], # year
103
+ date_parts[1], # month
104
+ date_parts[2], # day
105
+ time_parts[0], # hour
106
+ time_parts[1], # minute
107
+ 0, # second
108
+ '+00:00' # UTC timezone
109
+ )
110
+ rescue StandardError => e
111
+ warn "Failed to parse datetime from #{date_str} #{time_str}: #{e.message}"
112
+ nil
113
+ end
163
114
 
164
- def split
165
- @split ||= @node.text.split('.').map(&:to_i)
166
- end
115
+ def json_data
116
+ @json_data ||= api_client.get_movies(@cinema_id)
117
+ end
167
118
 
168
- def starting_at
169
- @starting_at ||= @date.to_time + (hour * 60 + min) * 60
119
+ def api_client
120
+ @api_client ||= Api.new
121
+ end
170
122
  end
171
123
  end
172
124
  end
@@ -12,18 +12,10 @@ module PicturehouseUk
12
12
  get("cinema/#{id}")
13
13
  end
14
14
 
15
- # get the cinema screenings page for passed id
16
- # @return [String]
17
- def whats_on(id)
18
- get("cinema/#{id}/Whats_On")
19
- rescue OpenURI::HTTPError
20
- ''
21
- end
22
-
23
15
  # get the cinema contact information page for passed id
24
16
  # @return [String]
25
- def info(id)
26
- get("cinema/info/#{id}")
17
+ def information(id)
18
+ get("cinema/#{id}/information")
27
19
  rescue OpenURI::HTTPError
28
20
  ''
29
21
  end
@@ -34,12 +26,18 @@ module PicturehouseUk
34
26
  get(nil)
35
27
  end
36
28
 
29
+ # get the cinemas listing page
30
+ # @return [String]
31
+ def cinemas
32
+ get("cinema")
33
+ end
34
+
37
35
  private
38
36
 
39
37
  def get(path)
40
38
  # SSL verification doesn't work on picturehouses.com
41
- open("https://www.picturehouses.com/#{path}",
42
- ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE).read
39
+ URI.open("https://www.picturehouses.com/#{path}",
40
+ ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE).read
43
41
  end
44
42
  end
45
43
  end
@@ -1,6 +1,6 @@
1
1
  # Ruby interface for http://www.picturehouses.co.uk
2
- # @version 4.0.0
2
+ # @version 5.0.0
3
3
  module PicturehouseUk
4
4
  # Gem version
5
- VERSION = '4.0.0'.freeze
5
+ VERSION = '5.0.0'.freeze
6
6
  end
@@ -3,6 +3,7 @@ require 'nokogiri'
3
3
 
4
4
  require_relative './picturehouse_uk/version'
5
5
 
6
+ require_relative './picturehouse_uk/internal/api'
6
7
  require_relative './picturehouse_uk/internal/parser/address'
7
8
  require_relative './picturehouse_uk/internal/parser/screenings'
8
9
  require_relative './picturehouse_uk/internal/title_sanitizer'
@@ -12,15 +12,14 @@ Gem::Specification.new do |spec|
12
12
  spec.homepage = ''
13
13
  spec.licenses = %w(AGPL MIT)
14
14
 
15
- spec.files = `git ls-files`.split($RS)
15
+ spec.files = `git ls-files`.split("\n")
16
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ['lib']
19
19
 
20
- spec.add_development_dependency 'bundler', '~> 1.3'
21
- spec.add_development_dependency 'codeclimate-test-reporter'
22
20
  spec.add_development_dependency 'minitest-reporters'
23
21
  spec.add_development_dependency 'rake'
22
+ spec.add_development_dependency 'simplecov'
24
23
  spec.add_development_dependency 'webmock'
25
24
 
26
25
  spec.add_runtime_dependency 'cinebase', '~> 3.0'