cineworld_uk 4.3.2-aarch64-linux-gnu → 4.4.0-aarch64-linux-gnu
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 +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -0
- data/README.md +19 -2
- data/cineworld_uk.gemspec +1 -1
- data/lib/cineworld_uk/cinema.rb +34 -0
- data/lib/cineworld_uk/internal/api_response.rb +4 -0
- data/lib/cineworld_uk/version.rb +2 -2
- data/lib/cineworld_uk.rb +5 -8
- data/test/fixtures/api/sites.json +3 -0
- data/test/lib/cineworld_uk/cinema_test.rb +19 -0
- data/test/lib/cineworld_uk/internal/api_response_test.rb +9 -0
- data/test/lib/cineworld_uk/internal/guest_token_test.rb +10 -0
- data/test/live/integration_test.rb +10 -0
- data/test/support/api_shapes.rb +5 -0
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a456ae797e684c4574b2e83e5cabc7d4b8e8102e939d8d422188f15e75670f4d
|
|
4
|
+
data.tar.gz: 16aa7ebd6a8aa9230f96a5b9c37247898d86685da0cf40685475e94ccc34df2f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: af53e95c142c67f2c5455ea7f52c20deb94f7c7721f39174ef59e2afc3903e117d689b119f02aac9146a2ea1465e840cb1e755a76754809a8ddc995a8acae52a
|
|
7
|
+
data.tar.gz: 48ca6620bbc63aa64cf3c67558dce6fb2256404875fa82c6cc135d5105e87c73938305b2f550322bf13182e14c1ddf6462b53079ce6f9fc87bb66ed1162caab7
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
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
|
+
## 4.4.0 - 2026-10-31
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- `Cinema#latitude` and `Cinema#longitude` as Floats in decimal degrees, from the Vista sites response. They are `nil` when a site has no location or sits at 0, 0.
|
|
9
|
+
- `CineworldUk.ensure_token!` fetches a guest token only when there is none or it expires within an hour, and `CineworldUk.token_expires_at` reads its expiry. Both come from cinebase's `Vista::TokenHolder`.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- A token the API rejects is cleared from `CineworldUk.token`, so the next `ensure_token!` fetches a fresh one.
|
|
13
|
+
- Requires cinebase 5.6.
|
|
14
|
+
|
|
5
15
|
## 4.3.2 - 2026-10-22
|
|
6
16
|
|
|
7
17
|
### Changed
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -36,6 +36,16 @@ CineworldUk.acquire_token!
|
|
|
36
36
|
CineworldUk::Cinema.all
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
`acquire_token!` always fetches a new token. `ensure_token!` fetches one only
|
|
40
|
+
when there is no token, or the token expires within an hour, and otherwise
|
|
41
|
+
keeps the current one. Call it before each batch of requests:
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
CineworldUk.ensure_token!
|
|
45
|
+
CineworldUk.token_expires_at
|
|
46
|
+
#=> 2026-10-31 03:00:00 UTC
|
|
47
|
+
```
|
|
48
|
+
|
|
39
49
|
This shells out to **`curl-impersonate`**, not ordinary system `curl`, using its
|
|
40
50
|
Chrome 150 TLS/HTTP profile. No Python, Chrome, JavaScript execution or browser
|
|
41
51
|
cookies are needed. Platform-specific gem packages include the pinned
|
|
@@ -89,8 +99,9 @@ The gem sends `Authorization: Bearer ...` and `Connect-Region-Code: GB` to
|
|
|
89
99
|
automatically.
|
|
90
100
|
|
|
91
101
|
Missing tokens and HTTP 401 responses raise `CineworldUk::AuthenticationError`.
|
|
92
|
-
|
|
93
|
-
|
|
102
|
+
A token the API rejects is cleared from `CineworldUk.token`, so call
|
|
103
|
+
`CineworldUk.ensure_token!`, or set `CineworldUk.token` with a fresh token,
|
|
104
|
+
before retrying. Tokens are never persisted by the gem. Other HTTP
|
|
94
105
|
failures raise an error rather than returning an empty schedule. Redirects are
|
|
95
106
|
not followed, so credentials are not forwarded to another host.
|
|
96
107
|
|
|
@@ -134,6 +145,12 @@ cinema.full_name
|
|
|
134
145
|
cinema.id
|
|
135
146
|
#=> 14
|
|
136
147
|
|
|
148
|
+
cinema.latitude
|
|
149
|
+
#=> 50.8125991821289
|
|
150
|
+
|
|
151
|
+
cinema.longitude
|
|
152
|
+
#=> -0.104699999094009
|
|
153
|
+
|
|
137
154
|
cinema.postal_code
|
|
138
155
|
#=> 'BN2 5UF'
|
|
139
156
|
```
|
data/cineworld_uk.gemspec
CHANGED
|
@@ -25,6 +25,6 @@ Gem::Specification.new do |spec|
|
|
|
25
25
|
spec.add_development_dependency 'simplecov', '< 1'
|
|
26
26
|
spec.add_development_dependency 'webmock'
|
|
27
27
|
|
|
28
|
-
spec.add_runtime_dependency 'cinebase', '~> 5.
|
|
28
|
+
spec.add_runtime_dependency 'cinebase', '~> 5.6'
|
|
29
29
|
spec.add_runtime_dependency 'nokogiri', '>= 1.11'
|
|
30
30
|
end
|
data/lib/cineworld_uk/cinema.rb
CHANGED
|
@@ -101,6 +101,26 @@ module CineworldUk
|
|
|
101
101
|
# cinema.locality
|
|
102
102
|
# #=> 'Brighton'
|
|
103
103
|
|
|
104
|
+
# Latitude of the cinema
|
|
105
|
+
# @return [Float, nil] decimal degrees, or nil when unknown
|
|
106
|
+
# @example
|
|
107
|
+
# cinema = CineworldUk::Cinema.new(14)
|
|
108
|
+
# cinema.latitude
|
|
109
|
+
# #=> 50.8125991821289
|
|
110
|
+
def latitude
|
|
111
|
+
coordinates&.first
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Longitude of the cinema
|
|
115
|
+
# @return [Float, nil] decimal degrees, or nil when unknown
|
|
116
|
+
# @example
|
|
117
|
+
# cinema = CineworldUk::Cinema.new(14)
|
|
118
|
+
# cinema.longitude
|
|
119
|
+
# #=> -0.104699999094009
|
|
120
|
+
def longitude
|
|
121
|
+
coordinates&.last
|
|
122
|
+
end
|
|
123
|
+
|
|
104
124
|
# The name of the cinema
|
|
105
125
|
# @return [String]
|
|
106
126
|
# @example
|
|
@@ -164,5 +184,19 @@ module CineworldUk
|
|
|
164
184
|
JSON.parse(api.cinema_list)['body']['cinemas']
|
|
165
185
|
end
|
|
166
186
|
private_class_method :cinema_list_json
|
|
187
|
+
|
|
188
|
+
private
|
|
189
|
+
|
|
190
|
+
def cinema_hash
|
|
191
|
+
formatted_id = @id.to_s.rjust(3, '0')
|
|
192
|
+
self.class.send(:cinema_list_json).find { |cinema| cinema['id'] == formatted_id } || {}
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# 0, 0 marks a site whose position was never set
|
|
196
|
+
def coordinates
|
|
197
|
+
location = cinema_hash['location'] || {}
|
|
198
|
+
pair = [location['latitude'], location['longitude']]
|
|
199
|
+
pair.map(&:to_f) if pair.all?(Numeric) && pair.any?(&:nonzero?)
|
|
200
|
+
end
|
|
167
201
|
end
|
|
168
202
|
end
|
|
@@ -25,6 +25,7 @@ module CineworldUk
|
|
|
25
25
|
{
|
|
26
26
|
"id" => site.fetch("id"),
|
|
27
27
|
"displayName" => site.fetch("name").fetch("text"),
|
|
28
|
+
"location" => site["location"],
|
|
28
29
|
"addressInfo" => {
|
|
29
30
|
"address1" => address.dig("line1", "text"),
|
|
30
31
|
"city" => address.dig("line2", "text"),
|
|
@@ -87,6 +88,9 @@ module CineworldUk
|
|
|
87
88
|
|
|
88
89
|
def fetch(path, query = {})
|
|
89
90
|
client.get(path, query)
|
|
91
|
+
rescue Cinebase::Vista::AuthenticationError
|
|
92
|
+
CineworldUk.reject_token!(@client_token)
|
|
93
|
+
raise
|
|
90
94
|
end
|
|
91
95
|
|
|
92
96
|
# One client keeps one connection open, so reuse it until the token changes.
|
data/lib/cineworld_uk/version.rb
CHANGED
data/lib/cineworld_uk.rb
CHANGED
|
@@ -20,13 +20,10 @@ require_relative './cineworld_uk/performance'
|
|
|
20
20
|
module CineworldUk
|
|
21
21
|
AuthenticationError = Cinebase::Vista::AuthenticationError
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def acquire_token!(curl: nil)
|
|
29
|
-
self.token = Internal::GuestToken.new(curl: curl).fetch
|
|
30
|
-
end
|
|
23
|
+
extend Cinebase::Vista::TokenHolder
|
|
24
|
+
|
|
25
|
+
# @api private
|
|
26
|
+
def self.guest_token_class
|
|
27
|
+
Internal::GuestToken
|
|
31
28
|
end
|
|
32
29
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
{
|
|
4
4
|
"id": "014",
|
|
5
5
|
"name": { "text": "Brighton" },
|
|
6
|
+
"location": { "latitude": 50.8125991821289, "longitude": -0.104699999094009 },
|
|
6
7
|
"contactDetails": {
|
|
7
8
|
"addressV2": {
|
|
8
9
|
"line1": { "text": "1 Example Marina" },
|
|
@@ -15,6 +16,7 @@
|
|
|
15
16
|
{
|
|
16
17
|
"id": "088",
|
|
17
18
|
"name": { "text": "Glasgow Silverburn" },
|
|
19
|
+
"location": { "latitude": 0, "longitude": 0 },
|
|
18
20
|
"contactDetails": {
|
|
19
21
|
"addressV2": {
|
|
20
22
|
"line1": { "text": "2 Example Centre" },
|
|
@@ -27,6 +29,7 @@
|
|
|
27
29
|
{
|
|
28
30
|
"id": "103",
|
|
29
31
|
"name": { "text": "Leicester Square" },
|
|
32
|
+
"location": null,
|
|
30
33
|
"contactDetails": {
|
|
31
34
|
"addressV2": {
|
|
32
35
|
"line1": { "text": "3 Example Square" },
|
|
@@ -61,6 +61,25 @@ class CineworldUk::CinemaTest < Minitest::Test
|
|
|
61
61
|
assert_equal 'Example: Riverside', CineworldUk::Cinema.new(999).name
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
+
def test_latitude_and_longitude
|
|
65
|
+
cinema = CineworldUk::Cinema.new(14)
|
|
66
|
+
|
|
67
|
+
assert_in_delta 50.8126, cinema.latitude, 0.0001
|
|
68
|
+
assert_in_delta(-0.1047, cinema.longitude, 0.0001)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_latitude_and_longitude_are_nil_without_a_location
|
|
72
|
+
[103, 999].each do |id|
|
|
73
|
+
assert_nil CineworldUk::Cinema.new(id).latitude
|
|
74
|
+
assert_nil CineworldUk::Cinema.new(id).longitude
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_latitude_and_longitude_are_nil_at_zero_zero
|
|
79
|
+
assert_nil CineworldUk::Cinema.new(88).latitude
|
|
80
|
+
assert_nil CineworldUk::Cinema.new(88).longitude
|
|
81
|
+
end
|
|
82
|
+
|
|
64
83
|
def test_locality
|
|
65
84
|
assert_equal 'Brighton', CineworldUk::Cinema.new(14).locality
|
|
66
85
|
assert_equal 'London', CineworldUk::Cinema.new(103).locality
|
|
@@ -68,6 +68,15 @@ class CineworldUk::Internal::ApiResponseTest < Minitest::Test
|
|
|
68
68
|
refute_includes error.message, "expired-secret"
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
+
def test_rejected_token_is_cleared
|
|
72
|
+
CineworldUk.token = "rejected-token"
|
|
73
|
+
stub_request(:get, "#{BASE_URL}sites").to_return(status: 401)
|
|
74
|
+
|
|
75
|
+
assert_raises(CineworldUk::AuthenticationError) { CineworldUk::Cinema.all }
|
|
76
|
+
|
|
77
|
+
assert_nil CineworldUk.token
|
|
78
|
+
end
|
|
79
|
+
|
|
71
80
|
def test_uses_replacement_token
|
|
72
81
|
CineworldUk.token = "replacement"
|
|
73
82
|
stub_request(:get, "#{BASE_URL}sites")
|
|
@@ -27,6 +27,16 @@ class CineworldUk::Internal::GuestTokenTest < Minitest::Test
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def test_ensure_token_fetches_only_without_a_current_token
|
|
31
|
+
CineworldUk.token = nil
|
|
32
|
+
html, token = token_page(Time.now.to_i + 7200)
|
|
33
|
+
serve_token_page(html)
|
|
34
|
+
|
|
35
|
+
assert_equal token, CineworldUk.ensure_token!(curl: @curl)
|
|
36
|
+
serve_token_page("", exit_code: 7)
|
|
37
|
+
assert_equal token, CineworldUk.ensure_token!(curl: @curl)
|
|
38
|
+
end
|
|
39
|
+
|
|
30
40
|
def test_rejects_expired_tokens_including_boundary_and_keeps_current_token
|
|
31
41
|
now = Time.at(1_800_000_000)
|
|
32
42
|
Time.stub(:now, now) do
|
|
@@ -8,6 +8,16 @@ class LiveCinemaTest < Minitest::Test
|
|
|
8
8
|
assert_operator cinemas.size, :>, 18
|
|
9
9
|
assert_equal 'Brighton', cinemas.detect { |cinema| cinema.id == 14 }.name
|
|
10
10
|
end
|
|
11
|
+
|
|
12
|
+
def test_cinemas_have_uk_coordinates
|
|
13
|
+
located = CineworldUk::Cinema.all.select(&:latitude)
|
|
14
|
+
|
|
15
|
+
refute_empty located
|
|
16
|
+
located.each do |cinema|
|
|
17
|
+
assert_includes 49.0..61.0, cinema.latitude, "#{cinema.id} #{cinema.name}"
|
|
18
|
+
assert_includes(-9.0..2.0, cinema.longitude, "#{cinema.id} #{cinema.name}")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
11
21
|
end
|
|
12
22
|
|
|
13
23
|
class LivePerformanceTest < Minitest::Test
|
data/test/support/api_shapes.rb
CHANGED
|
@@ -16,6 +16,11 @@ module ApiShapes
|
|
|
16
16
|
line = address.fetch(key)
|
|
17
17
|
assert_kind_of String, line.fetch('text'), "site #{site['id']} #{key}" unless line.nil?
|
|
18
18
|
end
|
|
19
|
+
location = site['location'] || {}
|
|
20
|
+
%w(latitude longitude).each do |key|
|
|
21
|
+
value = location[key]
|
|
22
|
+
assert_kind_of Numeric, value, "site #{site['id']} #{key}" unless value.nil?
|
|
23
|
+
end
|
|
19
24
|
end
|
|
20
25
|
end
|
|
21
26
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cineworld_uk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.4.0
|
|
5
5
|
platform: aarch64-linux-gnu
|
|
6
6
|
authors:
|
|
7
7
|
- Andy Croll
|
|
@@ -113,14 +113,14 @@ dependencies:
|
|
|
113
113
|
requirements:
|
|
114
114
|
- - "~>"
|
|
115
115
|
- !ruby/object:Gem::Version
|
|
116
|
-
version: '5.
|
|
116
|
+
version: '5.6'
|
|
117
117
|
type: :runtime
|
|
118
118
|
prerelease: false
|
|
119
119
|
version_requirements: !ruby/object:Gem::Requirement
|
|
120
120
|
requirements:
|
|
121
121
|
- - "~>"
|
|
122
122
|
- !ruby/object:Gem::Version
|
|
123
|
-
version: '5.
|
|
123
|
+
version: '5.6'
|
|
124
124
|
- !ruby/object:Gem::Dependency
|
|
125
125
|
name: nokogiri
|
|
126
126
|
requirement: !ruby/object:Gem::Requirement
|