cineworld_uk 3.1.0 → 4.1.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 +5 -5
- data/.agents/setup +51 -0
- data/.github/workflows/test.yml +43 -0
- data/.gitignore +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +21 -0
- data/README.md +136 -16
- data/Rakefile +5 -37
- data/cineworld_uk.gemspec +7 -4
- data/lib/cineworld_uk/cinema.rb +7 -4
- data/lib/cineworld_uk/internal/api_response.rb +99 -56
- data/lib/cineworld_uk/internal/guest_token.rb +73 -0
- data/lib/cineworld_uk/internal/parser/api/cinema_address.rb +24 -24
- data/lib/cineworld_uk/internal/parser/api/film.rb +10 -8
- data/lib/cineworld_uk/internal/parser/api/performance.rb +6 -11
- data/lib/cineworld_uk/performance.rb +42 -23
- data/lib/cineworld_uk/version.rb +2 -2
- data/lib/cineworld_uk.rb +12 -2
- data/tasks/package.rake +84 -0
- data/test/fixtures/api/cinema-list.json +1 -1
- data/test/fixtures/api/dates-14.json +1 -0
- data/test/fixtures/api/performances-tomorrow-14.json +1 -0
- data/test/fixtures/api/vista-showtimes-brighton.json +1 -0
- data/test/lib/cineworld_uk/cinema_test.rb +47 -47
- data/test/lib/cineworld_uk/internal/api_response_test.rb +177 -58
- data/test/lib/cineworld_uk/internal/parser/api/cinema_address_test.rb +14 -14
- data/test/lib/cineworld_uk/internal/parser/api/film_test.rb +43 -55
- data/test/lib/cineworld_uk/internal/parser/api/performance_test.rb +11 -12
- data/test/lib/cineworld_uk/internal/title_sanitizer_test.rb +18 -18
- data/test/lib/cineworld_uk/performance_test.rb +31 -32
- data/test/lib/cineworld_uk/version_test.rb +1 -1
- data/test/live/integration_test.rb +9 -9
- data/test/package_test.rb +49 -0
- data/test/support/fixture_reader.rb +2 -14
- data/test/test_helper.rb +3 -2
- metadata +65 -36
- data/.travis.yml +0 -10
- data/lib/cineworld_uk/internal/parser/api/film_lookup.rb +0 -38
- data/lib/cineworld_uk/internal/parser/api/performances_by_day.rb +0 -54
- data/test/fixtures/api/cinema-detail-10.json +0 -1
- data/test/fixtures/api/cinema-detail-21.json +0 -1
- data/test/fixtures/api/cinema-detail-3.json +0 -1
- data/test/fixtures/api/cinema-detail-96.json +0 -1
- data/test/fixtures/api/dates-3.json +0 -1
- data/test/fixtures/api/film-list-comingsoon.json +0 -1
- data/test/fixtures/api/film-list.json +0 -1
- data/test/fixtures/api/performances-tomorrow-3.json +0 -1
- data/test/lib/cineworld_uk/internal/parser/api/film_lookup_test.rb +0 -31
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
require "json"
|
|
5
|
+
require "nokogiri"
|
|
6
|
+
require "open3"
|
|
7
|
+
|
|
8
|
+
module CineworldUk
|
|
9
|
+
module Internal
|
|
10
|
+
# Retrieves the public guest token without running a browser.
|
|
11
|
+
class GuestToken
|
|
12
|
+
def initialize(curl:)
|
|
13
|
+
@curl = curl || default_curl
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def fetch
|
|
17
|
+
token = extract_token(request_page)
|
|
18
|
+
validate_expiry!(token)
|
|
19
|
+
token
|
|
20
|
+
rescue JSON::ParserError, ArgumentError, IndexError, TypeError, NoMethodError
|
|
21
|
+
raise AuthenticationError, "Guest token page data is missing or invalid", cause: nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def default_curl
|
|
27
|
+
bundled = File.expand_path("../../../vendor/curl-impersonate/bin/curl-impersonate", __dir__)
|
|
28
|
+
File.executable?(bundled) ? bundled : "curl-impersonate"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def curl_command
|
|
32
|
+
[@curl, "--disable", "--impersonate", "chrome150",
|
|
33
|
+
"--compressed", "--silent", "--show-error",
|
|
34
|
+
"--connect-timeout", "10", "--max-time", "30",
|
|
35
|
+
"--write-out", "\n%{http_code}", "https://web.cineworld.co.uk/"]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def request_page
|
|
39
|
+
output, _stderr, result = Open3.capture3(*curl_command)
|
|
40
|
+
unless result.success?
|
|
41
|
+
raise AuthenticationError,
|
|
42
|
+
"Guest token request failed (curl exit #{result.exitstatus})"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
html, _, status = output.rpartition("\n")
|
|
46
|
+
unless %w[200 404].include?(status)
|
|
47
|
+
raise AuthenticationError, "Guest token page returned HTTP #{status}"
|
|
48
|
+
end
|
|
49
|
+
html
|
|
50
|
+
rescue Errno::ENOENT
|
|
51
|
+
raise AuthenticationError,
|
|
52
|
+
"Install curl-impersonate or pass its executable path with curl:"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def extract_token(html)
|
|
56
|
+
script = Nokogiri::HTML(html).at_css("script#__NEXT_DATA__")
|
|
57
|
+
data = JSON.parse(script ? script.content : "")
|
|
58
|
+
token = data.dig("props", "pageProps", "environment", "gasToken")
|
|
59
|
+
unless token.is_a?(String) && !token.empty?
|
|
60
|
+
raise AuthenticationError, "Guest token is missing from the page"
|
|
61
|
+
end
|
|
62
|
+
token
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def validate_expiry!(token)
|
|
66
|
+
claims = JSON.parse(Base64.urlsafe_decode64(token.split(".").fetch(1)))
|
|
67
|
+
if Integer(claims.fetch("exp")) <= Time.now.to_i
|
|
68
|
+
raise AuthenticationError, "Guest token supplied by the page has expired"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -7,8 +7,9 @@ module CineworldUk
|
|
|
7
7
|
class CinemaAddress
|
|
8
8
|
# @param [Integer] id the cinema id
|
|
9
9
|
# @return [CineworldUk::Internal::Parser::Api::CinemaAddress]
|
|
10
|
-
def initialize(id)
|
|
10
|
+
def initialize(id, cinemas = nil)
|
|
11
11
|
@id = id
|
|
12
|
+
@cinemas = cinemas
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
# @return [Hash] contains :street_address, :extended_address,
|
|
@@ -27,52 +28,51 @@ module CineworldUk
|
|
|
27
28
|
|
|
28
29
|
private
|
|
29
30
|
|
|
30
|
-
def
|
|
31
|
-
@
|
|
32
|
-
cinema_detail_hash['address'].split(',').map(&:strip).compact
|
|
31
|
+
def address_info
|
|
32
|
+
@address_info ||= cinema_hash['addressInfo'] || {}
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
def
|
|
36
|
-
@
|
|
35
|
+
def cinema_hash
|
|
36
|
+
@cinema_hash ||= begin
|
|
37
|
+
cinemas = @cinemas ||
|
|
38
|
+
JSON.parse(cinema_list_response)["body"]["cinemas"]
|
|
39
|
+
formatted_id = @id.to_s.rjust(3, '0')
|
|
40
|
+
cinemas.find { |c| c['id'] == formatted_id } || {}
|
|
41
|
+
end
|
|
37
42
|
end
|
|
38
43
|
|
|
39
|
-
def
|
|
40
|
-
@
|
|
41
|
-
CineworldUk::Internal::ApiResponse.new.
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def ext_array
|
|
45
|
-
@ext_array ||= adr_array[1..-1]
|
|
44
|
+
def cinema_list_response
|
|
45
|
+
@cinema_list_response ||=
|
|
46
|
+
CineworldUk::Internal::ApiResponse.new.cinema_list
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def extended_address
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
end
|
|
50
|
+
addr2 = address_info['address2']
|
|
51
|
+
addr3 = address_info['address3']
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
return nil if london?
|
|
54
|
+
addr2 || addr3
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def locality
|
|
58
|
-
|
|
59
|
-
london? ? ext_array[0] : ext_array[1]
|
|
58
|
+
address_info['city']
|
|
60
59
|
end
|
|
61
60
|
|
|
62
61
|
def london?
|
|
63
|
-
|
|
62
|
+
address_info['city'] == 'London' ||
|
|
63
|
+
cinema_hash['displayName']&.start_with?('London')
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def postal_code
|
|
67
|
-
|
|
67
|
+
address_info['postalCode']
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def region
|
|
71
|
-
'London' if london?
|
|
71
|
+
address_info['state'] || ('London' if london?)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
def street_address
|
|
75
|
-
|
|
75
|
+
address_info['address1']
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
end
|
|
@@ -12,31 +12,33 @@ module CineworldUk
|
|
|
12
12
|
# @return [ CineworldUk::Internal::Parser::Api::Film]
|
|
13
13
|
def initialize(data)
|
|
14
14
|
@data = data
|
|
15
|
-
@id = @data['
|
|
15
|
+
@id = @data['id']
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# Do you need your 3D glasses?
|
|
19
19
|
# @return [String] either '2d' or '3d'
|
|
20
20
|
def dimension
|
|
21
|
-
@data['
|
|
21
|
+
@data['attributeIds']&.include?('3d') ? '3d' : '2d'
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
# Sanitized film name
|
|
25
25
|
# @return [String]
|
|
26
26
|
def name
|
|
27
|
-
|
|
27
|
+
title = @data['name'] || ''
|
|
28
|
+
TitleSanitizer.new(title).sanitized
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
# List of strings representing different kinds of performance, such
|
|
31
32
|
# as autism, kids, imax, members or q&a
|
|
32
33
|
# @return [Array<String>] or an empty array
|
|
33
34
|
def variant
|
|
35
|
+
attrs = @data['attributeIds'] || []
|
|
34
36
|
[
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
attrs.include?('autism-friendly') ? 'autism_friendly' : nil,
|
|
38
|
+
attrs.include?('imax') ? 'imax' : nil,
|
|
39
|
+
attrs.include?('junior') ? 'kids' : nil,
|
|
40
|
+
attrs.include?('unlimited-screening') ? 'members' : nil,
|
|
41
|
+
attrs.include?('qa') ? 'q&a' : nil
|
|
40
42
|
].compact
|
|
41
43
|
end
|
|
42
44
|
end
|
|
@@ -13,32 +13,27 @@ module CineworldUk
|
|
|
13
13
|
|
|
14
14
|
# @return [String] direct booking url
|
|
15
15
|
def booking_url
|
|
16
|
-
|
|
16
|
+
@data['bookingLink']
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# @return [Integer] id for film lookup
|
|
20
20
|
def film_id
|
|
21
|
-
@data['
|
|
21
|
+
@data['filmId']
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
# @return [DateTime] in local time
|
|
25
25
|
def starting_at
|
|
26
|
-
Time.
|
|
26
|
+
Time.parse(@data['eventDateTime'])
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
# @return [Array<String>] includes audio described & subtitled
|
|
30
30
|
def variant
|
|
31
|
+
attrs = @data['attributeIds'] || []
|
|
31
32
|
[
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
attrs.include?('audio-described') ? 'audio_described' : nil,
|
|
34
|
+
attrs.include?('subbed') ? 'subtitled' : nil
|
|
34
35
|
].compact
|
|
35
36
|
end
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
def time_str
|
|
40
|
-
"#{@data['date']} #{@data['time']}"
|
|
41
|
-
end
|
|
42
37
|
end
|
|
43
38
|
end
|
|
44
39
|
end
|
|
@@ -22,14 +22,22 @@ module CineworldUk
|
|
|
22
22
|
# @option options [String] :film_name name of the film
|
|
23
23
|
# @option options [Time] :starting_at listed start time of the performance
|
|
24
24
|
|
|
25
|
-
#
|
|
25
|
+
# Performances within an inclusive range of cinema business dates.
|
|
26
26
|
# @param [Integer] cinema_id id of the cinema on the website
|
|
27
|
-
# @
|
|
28
|
-
|
|
27
|
+
# @param [Date] from first date (defaults to today in London)
|
|
28
|
+
# @param [Date] to last date (defaults to 13 days after from)
|
|
29
|
+
# @return [Array<CineworldUk::Performance>]
|
|
30
|
+
def self.at(
|
|
31
|
+
cinema_id,
|
|
32
|
+
from: TZInfo::Timezone.get("Europe/London").now.to_date,
|
|
33
|
+
to: from + 13
|
|
34
|
+
)
|
|
29
35
|
cinema_id = cinema_id.to_i
|
|
30
|
-
|
|
36
|
+
raise ArgumentError, "to must not precede from" if to < from
|
|
37
|
+
|
|
38
|
+
(from..to).flat_map do |date|
|
|
31
39
|
performances_on(cinema_id, date).flat_map do |p|
|
|
32
|
-
new
|
|
40
|
+
new({ cinema_id: cinema_id }.merge(p))
|
|
33
41
|
end
|
|
34
42
|
end
|
|
35
43
|
end
|
|
@@ -55,31 +63,42 @@ module CineworldUk
|
|
|
55
63
|
private_class_method :api
|
|
56
64
|
|
|
57
65
|
# @api private
|
|
58
|
-
def self.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
end
|
|
64
|
-
private_class_method :cinema_hash
|
|
66
|
+
def self.performances_on(cinema_id, date)
|
|
67
|
+
response = JSON.parse(api.performances(cinema_id, date))
|
|
68
|
+
films_hash = build_films_hash(response['body']['films'])
|
|
69
|
+
events = response['body']['events']
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
events.map do |event_data|
|
|
72
|
+
performance = Internal::Parser::Api::Performance.new(event_data)
|
|
73
|
+
film = films_hash[performance.film_id]
|
|
74
|
+
|
|
75
|
+
{
|
|
76
|
+
cinema_name: response["body"]["cinemaName"] ||
|
|
77
|
+
CineworldUk::Cinema.new(cinema_id).name,
|
|
78
|
+
booking_url: performance.booking_url,
|
|
79
|
+
dimension: film.dimension,
|
|
80
|
+
film_name: film.name,
|
|
81
|
+
starting_at: utc(performance.starting_at),
|
|
82
|
+
variant: (performance.variant + film.variant).sort
|
|
83
|
+
}
|
|
70
84
|
end
|
|
71
85
|
end
|
|
72
|
-
private_class_method :
|
|
86
|
+
private_class_method :performances_on
|
|
73
87
|
|
|
74
88
|
# @api private
|
|
75
|
-
def self.
|
|
76
|
-
|
|
89
|
+
def self.build_films_hash(films_array)
|
|
90
|
+
films_array.each_with_object({}) do |film_data, hash|
|
|
91
|
+
film = Internal::Parser::Api::Film.new(film_data)
|
|
92
|
+
hash[film_data['id']] = film
|
|
93
|
+
end
|
|
77
94
|
end
|
|
78
|
-
private_class_method :
|
|
95
|
+
private_class_method :build_films_hash
|
|
79
96
|
|
|
80
|
-
|
|
81
|
-
|
|
97
|
+
# @api private
|
|
98
|
+
def self.utc(time)
|
|
99
|
+
return time if time.utc?
|
|
100
|
+
TZInfo::Timezone.get('Europe/London').local_to_utc(time)
|
|
82
101
|
end
|
|
83
|
-
private_class_method :
|
|
102
|
+
private_class_method :utc
|
|
84
103
|
end
|
|
85
104
|
end
|
data/lib/cineworld_uk/version.rb
CHANGED
data/lib/cineworld_uk.rb
CHANGED
|
@@ -5,10 +5,9 @@ require 'cinebase'
|
|
|
5
5
|
require_relative './cineworld_uk/version'
|
|
6
6
|
|
|
7
7
|
require_relative './cineworld_uk/internal/api_response'
|
|
8
|
+
require_relative './cineworld_uk/internal/guest_token'
|
|
8
9
|
require_relative './cineworld_uk/internal/parser/api/cinema_address'
|
|
9
10
|
require_relative './cineworld_uk/internal/parser/api/film'
|
|
10
|
-
require_relative './cineworld_uk/internal/parser/api/film_lookup'
|
|
11
|
-
require_relative './cineworld_uk/internal/parser/api/performances_by_day'
|
|
12
11
|
require_relative './cineworld_uk/internal/parser/api/performance'
|
|
13
12
|
|
|
14
13
|
require_relative './cineworld_uk/internal/title_sanitizer'
|
|
@@ -18,4 +17,15 @@ require_relative './cineworld_uk/performance'
|
|
|
18
17
|
|
|
19
18
|
# cineworld_uk gem
|
|
20
19
|
module CineworldUk
|
|
20
|
+
class AuthenticationError < StandardError; end
|
|
21
|
+
|
|
22
|
+
# A raw guest JWT, without the "Bearer " prefix. Never persisted by the gem.
|
|
23
|
+
class << self
|
|
24
|
+
attr_accessor :token
|
|
25
|
+
|
|
26
|
+
# Explicit acquisition/renewal; ordinary API calls never launch a subprocess.
|
|
27
|
+
def acquire_token!(curl: nil)
|
|
28
|
+
self.token = Internal::GuestToken.new(curl: curl).fetch
|
|
29
|
+
end
|
|
30
|
+
end
|
|
21
31
|
end
|
data/tasks/package.rake
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "rubygems/package"
|
|
6
|
+
require "tmpdir"
|
|
7
|
+
require "zlib"
|
|
8
|
+
|
|
9
|
+
namespace :package do
|
|
10
|
+
# SHA-256 digests from the upstream v2.2.3 release assets.
|
|
11
|
+
releases = {
|
|
12
|
+
"x86_64-linux-gnu" => ["x86_64-linux-gnu", "ca7c8aae49e33260d3a2400db16c7737aaf04692d606a843502056b42990f989"],
|
|
13
|
+
"aarch64-linux-gnu" => ["aarch64-linux-gnu", "5e71795b971f32be8f3d7785895f4dceb232f04414f5a067db266432a5b08657"],
|
|
14
|
+
"arm64-darwin" => ["arm64-macos", "2569f4139460fcb301484d37938de91b1c220efd15487ee22a9db554262062fe"],
|
|
15
|
+
"x86_64-darwin" => ["x86_64-macos", "4686806d59abea93866a917c3025a049ef3d7a3240de742ad66bd1a4d9890dc7"]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
desc "Build a gem with bundled curl-impersonate 2.2.3 for the given platform"
|
|
19
|
+
task :native, [:platform] do |_task, args|
|
|
20
|
+
platform = args.fetch(:platform)
|
|
21
|
+
target, digest = releases.fetch(platform)
|
|
22
|
+
root = File.expand_path("..", __dir__)
|
|
23
|
+
asset = "curl-impersonate-v2.2.3.#{target}.tar.gz"
|
|
24
|
+
url = "https://github.com/lexiforest/curl-impersonate/releases/download/v2.2.3/#{asset}"
|
|
25
|
+
archive = File.join(root, "pkg", "downloads", asset)
|
|
26
|
+
FileUtils.mkdir_p(File.dirname(archive))
|
|
27
|
+
unless File.exist?(archive)
|
|
28
|
+
sh "curl", "--fail", "--location", "--retry", "3", "--output", archive, url
|
|
29
|
+
end
|
|
30
|
+
abort "SHA-256 mismatch for #{archive}; delete it and retry" unless Digest::SHA256.file(archive).hexdigest == digest
|
|
31
|
+
|
|
32
|
+
spec = Gem::Specification.load(File.join(root, "cineworld_uk.gemspec")).dup
|
|
33
|
+
Dir.mktmpdir("cineworld-package") do |stage|
|
|
34
|
+
spec.files.each do |file|
|
|
35
|
+
destination = File.join(stage, file)
|
|
36
|
+
FileUtils.mkdir_p(File.dirname(destination))
|
|
37
|
+
FileUtils.cp(File.join(root, file), destination)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
vendor = File.join(stage, "vendor", "curl-impersonate")
|
|
41
|
+
Zlib::GzipReader.open(archive) do |gzip|
|
|
42
|
+
Gem::Package::TarReader.new(gzip) do |tar|
|
|
43
|
+
tar.each do |entry|
|
|
44
|
+
next unless entry.file?
|
|
45
|
+
|
|
46
|
+
name = entry.full_name
|
|
47
|
+
relative = if name == "curl-impersonate"
|
|
48
|
+
"bin/curl-impersonate"
|
|
49
|
+
elsif name.start_with?("LICENSE") && File.basename(name) == name
|
|
50
|
+
"licenses/#{name}"
|
|
51
|
+
end
|
|
52
|
+
next unless relative
|
|
53
|
+
|
|
54
|
+
destination = File.join(vendor, relative)
|
|
55
|
+
FileUtils.mkdir_p(File.dirname(destination))
|
|
56
|
+
File.binwrite(destination, entry.read)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
File.chmod(0o755, File.join(vendor, "bin", "curl-impersonate"))
|
|
61
|
+
File.write(File.join(vendor, "SOURCE"), <<~SOURCE)
|
|
62
|
+
curl-impersonate 2.2.3
|
|
63
|
+
Binary: #{url}
|
|
64
|
+
SHA-256: #{digest}
|
|
65
|
+
Source and build instructions: https://github.com/lexiforest/curl-impersonate/tree/v2.2.3
|
|
66
|
+
Redistribution notices: licenses/
|
|
67
|
+
SOURCE
|
|
68
|
+
|
|
69
|
+
Dir.chdir(stage) do
|
|
70
|
+
spec.platform = Gem::Platform.new(platform)
|
|
71
|
+
spec.files += Dir.glob("vendor/**/*").select { |file| File.file?(file) }
|
|
72
|
+
Gem::Package.build(spec, false, false, File.join(root, "pkg", spec.file_name))
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
desc "Build all supported platform gems with bundled curl-impersonate"
|
|
78
|
+
task :all do
|
|
79
|
+
releases.each_key do |platform|
|
|
80
|
+
Rake::Task["package:native"].reenable
|
|
81
|
+
Rake::Task["package:native"].invoke(platform)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|