wtw_uk 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.
data/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # WtwUk
2
+
3
+ A simple gem to pull cinemas and performances from the [WTW Cinemas website](https://wtwcinemas.co.uk) and spit out useful formatted info.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'wtw_uk'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install wtw_uk
18
+
19
+ ## Usage
20
+
21
+ The gem conforms to the API set down in the `cinebase` gem, [andycroll/cinebase](https://github.com/andycroll/cinebase), which provides a lot of useful base vocabulary and repetitive code for this series of cinema focussed gems.
22
+
23
+ Performance titles are sanitized as much as possible, removing years,
24
+ subtitle, preview, autism friendly, Q&A and film club markers, and naming
25
+ National Theatre Live, Royal Ballet and Opera and Exhibition on Screen
26
+ screenings in full.
27
+
28
+ No token or setup is needed. WTW's WordPress website runs Jacro's cinema
29
+ plugin, with a subsite for each venue. Tickets are sold through TapOS,
30
+ behind each venue's own booking pages.
31
+
32
+ ### Cinema
33
+
34
+ The gem holds WTW's four Cornish venues, keyed by the TapOS site code in
35
+ their booking pages: subsites and Jacro cinema ids from the home page,
36
+ addresses from each venue's page footer and coordinates from OpenStreetMap.
37
+ Cinema methods make no requests.
38
+
39
+ ``` ruby
40
+ WtwUk::Cinema.all
41
+ #=> [<WtwUk::Cinema ...>, <WtwUk::Cinema ...>, ...]
42
+
43
+ cinema = WtwUk::Cinema.new('PLATRU')
44
+ #=> <WtwUk::Cinema ...>
45
+
46
+ cinema.adr
47
+ #=> {
48
+ street_address: '69 Lemon Street',
49
+ extended_address: nil,
50
+ locality: 'Truro',
51
+ region: 'Cornwall',
52
+ postal_code: 'TR1 2PN',
53
+ country_name: 'United Kingdom'
54
+ }
55
+
56
+ cinema.brand
57
+ #=> 'WTW Cinemas'
58
+
59
+ cinema.full_name
60
+ #=> 'WTW Cinemas Truro'
61
+
62
+ cinema.id
63
+ #=> 'PLATRU'
64
+
65
+ cinema.latitude
66
+ #=> 50.261851
67
+
68
+ cinema.url
69
+ #=> 'https://wtwcinemas.co.uk/truro/'
70
+ ```
71
+
72
+ | id | name |
73
+ | --- | --- |
74
+ | `WTWNEW` | Newquay (Lighthouse Cinema) |
75
+ | `FILAUS` | St Austell (White River Cinema) |
76
+ | `PLATRU` | Truro (The Plaza) |
77
+ | `REGWAD` | Wadebridge (The Regal) |
78
+
79
+ ### Performances
80
+
81
+ `Performance.at` returns performances for an inclusive range of showing dates,
82
+ defaulting to today in London and the following 13 days. The what's on page's
83
+ 'All Shows' request lists every showtime the venue has on sale, so any range
84
+ is one request.
85
+
86
+ ``` ruby
87
+ WtwUk::Performance.at('PLATRU', from: Date.today, to: Date.today + 2)
88
+ #=> [<WtwUk::Performance ...>, <WtwUk::Performance ...>, ...]
89
+
90
+ performance = WtwUk::Performance.at('PLATRU').first
91
+ #=> <WtwUk::Performance ...>
92
+
93
+ performance.film_name
94
+ #=> 'Heart of the Beast' # from 'Heart of the Beast (with subtitles)'
95
+
96
+ performance.film_year
97
+ #=> nil # from the title, e.g. 1971 for 'The Devils (1971)'
98
+
99
+ performance.dimension
100
+ #=> '2d'
101
+
102
+ performance.variant
103
+ #=> ['senior', 'subtitled']
104
+
105
+ performance.subtitled?
106
+ #=> true
107
+
108
+ performance.festival
109
+ #=> nil
110
+
111
+ performance.starting_at
112
+ #=> 2026-11-12 11:15:00 UTC
113
+
114
+ performance.booking_url
115
+ #=> 'https://wtwcinemas.co.uk/truro/booknow/122882/'
116
+
117
+ performance.cinema_name
118
+ #=> 'Truro'
119
+
120
+ performance.cinema_id
121
+ #=> 'PLATRU'
122
+ ```
123
+
124
+ Booking links go to the venue's booking page, which holds the TapOS seat
125
+ selection. Showtimes already passed today have no booking link.
126
+
127
+ Variants come from each showtime's classes and the title: `arts` (event
128
+ cinema: theatre, opera, ballet, musicals, concerts and exhibitions), `q&a`,
129
+ `relaxed` (autism friendly), `senior` (Silver Screen) and `subtitled`. Many
130
+ screenings offer audio description headsets or caption glasses, so neither
131
+ is a variant. Laser projection, strobe warnings and ticket offers are not
132
+ variants either.
133
+
134
+ ## Tests
135
+
136
+ ```sh
137
+ bundle exec rake # unit tests against fixtures
138
+ bundle exec rake live # live wtwcinemas.co.uk
139
+ ```
140
+
141
+ The fixture in `test/fixtures` is Truro's programme, trimmed to a few films
142
+ with shortened descriptions. `test/support/api_shapes.rb` describes the
143
+ markup the gem reads. The unit suite checks the fixture against it and the
144
+ live suite checks every venue's real programme, held only in memory, along
145
+ with the venue list and each venue's TapOS code. When the markup changes,
146
+ update the shape first, then the fixture.
147
+
148
+ ## Releasing
149
+
150
+ Bump the version, merge, then run the **Release Gem** workflow in GitHub
151
+ Actions. It runs the tests, tags the version and publishes the gem through
152
+ RubyGems trusted publishing.
153
+
154
+ ## Contributing
155
+
156
+ 1. Fork it
157
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
158
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
159
+ 4. Push to the branch (`git push origin my-new-feature`)
160
+ 5. Create new Pull Request
@@ -0,0 +1,130 @@
1
+ module WtwUk
2
+ # The object representing a cinema on the WTW Cinemas website
3
+ class Cinema < Cinebase::Cinema
4
+ # @!attribute [r] id
5
+ # @return [String] the venue's TapOS site code, e.g. 'PLATRU'
6
+
7
+ # Each venue is a subsite, and its programme request names it by Jacro
8
+ # cinema id. Neither page names the TapOS site code its booking pages
9
+ # use, and no page gives coordinates, so the gem holds the venues: names,
10
+ # subsites and cinema ids from the quick booking menu, codes from booking
11
+ # pages, addresses from venue page footers and coordinates from
12
+ # OpenStreetMap.
13
+ VENUES = {
14
+ 'WTWNEW' => {
15
+ name: 'Newquay', path: 'newquay', location: '5', street_address: 'King Street', locality: 'Newquay',
16
+ region: 'Cornwall', postal_code: 'TR7 1AA', latitude: 50.4136279, longitude: -5.0873384
17
+ },
18
+ 'FILAUS' => {
19
+ name: 'St Austell', path: 'st-austell', location: '1', street_address: 'White River Place',
20
+ locality: 'St Austell', region: 'Cornwall', postal_code: 'PL25 5AZ', latitude: 50.3376527,
21
+ longitude: -4.7948318
22
+ },
23
+ 'PLATRU' => {
24
+ name: 'Truro', path: 'truro', location: '2', street_address: '69 Lemon Street', locality: 'Truro',
25
+ region: 'Cornwall', postal_code: 'TR1 2PN', latitude: 50.261851, longitude: -5.0523149
26
+ },
27
+ 'REGWAD' => {
28
+ name: 'Wadebridge', path: 'wadebridge', location: '3', street_address: 'The Platt', locality: 'Wadebridge',
29
+ region: 'Cornwall', postal_code: 'PL27 7AD', latitude: 50.5152411, longitude: -4.8361756
30
+ }
31
+ }.freeze
32
+
33
+ ADDRESS_PARTS = %i(street_address extended_address locality region postal_code).freeze
34
+ WEBSITE = 'https://wtwcinemas.co.uk'.freeze
35
+
36
+ # Constructor
37
+ # @param [String] id the venue's TapOS site code, e.g. 'PLATRU' or 'platru'
38
+ # @return [WtwUk::Cinema]
39
+ def initialize(id)
40
+ @id = id.to_s.upcase
41
+ end
42
+
43
+ # Return basic cinema information for all cinemas
44
+ # @return [Array<WtwUk::Cinema>]
45
+ # @example
46
+ # WtwUk::Cinema.all
47
+ # #=> [<WtwUk::Cinema>, <WtwUk::Cinema>, ...]
48
+ def self.all
49
+ VENUES.keys.map { |id| new(id) }
50
+ end
51
+
52
+ # @!method address
53
+ # Address of the cinema
54
+ # @return [Hash] of different address parts
55
+ # @see #adr
56
+
57
+ # Address of the cinema
58
+ # @return [Hash] contains :street_address, :extended_address,
59
+ # :locality, :region, :postal_code, :country_name
60
+ # @example
61
+ # cinema = WtwUk::Cinema.new('PLATRU')
62
+ # cinema.adr
63
+ # #=> {
64
+ # street_address: '69 Lemon Street',
65
+ # extended_address: nil,
66
+ # locality: 'Truro',
67
+ # region: 'Cornwall',
68
+ # postal_code: 'TR1 2PN',
69
+ # country_name: 'United Kingdom'
70
+ # }
71
+ # @note Uses method naming as at http://microformats.org/wiki/adr
72
+ def adr
73
+ ADDRESS_PARTS.to_h { |part| [part, venue[part]] }.merge(country_name: 'United Kingdom')
74
+ end
75
+
76
+ # Brand of the cinema
77
+ # @return [String] which will always be 'WTW Cinemas'
78
+ def brand
79
+ 'WTW Cinemas'.freeze
80
+ end
81
+
82
+ # @return [Float, nil]
83
+ def latitude
84
+ venue[:latitude]
85
+ end
86
+
87
+ # Jacro's cinema id for the venue
88
+ # @return [String, nil]
89
+ # @api private
90
+ def location
91
+ venue[:location]
92
+ end
93
+
94
+ # @return [Float, nil]
95
+ def longitude
96
+ venue[:longitude]
97
+ end
98
+
99
+ # The name of the cinema
100
+ # @return [String]
101
+ # @example
102
+ # WtwUk::Cinema.new('FILAUS').name
103
+ # #=> 'St Austell'
104
+ def name
105
+ venue[:name].to_s
106
+ end
107
+
108
+ # The venue's subsite on the WTW Cinemas website
109
+ # @return [String, nil]
110
+ # @api private
111
+ def path
112
+ venue[:path]
113
+ end
114
+
115
+ # The url of the cinema's pages on the WTW Cinemas website
116
+ # @return [String]
117
+ # @example
118
+ # WtwUk::Cinema.new('PLATRU').url
119
+ # #=> 'https://wtwcinemas.co.uk/truro/'
120
+ def url
121
+ path ? "#{WEBSITE}/#{path}/" : ''
122
+ end
123
+
124
+ private
125
+
126
+ def venue
127
+ VENUES.fetch(id, {})
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+
5
+ module WtwUk
6
+ # Internal utility classes: Do not use
7
+ # @api private
8
+ module Internal
9
+ # Requests to wtwcinemas.co.uk
10
+ module Http
11
+ RETRIES = 2
12
+ TRANSIENT_ERRORS = [
13
+ EOFError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError
14
+ ].freeze
15
+
16
+ private
17
+
18
+ def post(url, form)
19
+ uri = URI(url)
20
+ request = Net::HTTP::Post.new(uri)
21
+ request.set_form_data(form)
22
+ attempts = 0
23
+ begin
24
+ response = Net::HTTP.start(uri.host, uri.port, use_ssl: true, open_timeout: 10, read_timeout: 30) do |http|
25
+ http.request(request)
26
+ end
27
+ rescue *TRANSIENT_ERRORS
28
+ attempts += 1
29
+ raise if attempts > RETRIES
30
+
31
+ sleep(attempts)
32
+ retry
33
+ end
34
+ # Omit response bodies from errors, and never follow redirects.
35
+ raise "WTW Cinemas HTTP error #{response.code}" unless response.is_a?(Net::HTTPSuccess)
36
+
37
+ String.new(response.body, encoding: Encoding::UTF_8)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WtwUk
4
+ # @api private
5
+ module Internal
6
+ module Parser
7
+ # Reads a venue's whole programme: a block for each film, with its
8
+ # showtimes in order under date headings such as
9
+ # '<strong>Wednesday </strong>16 December 2026'
10
+ class Programme
11
+ FILM = '<div class="poster-case '
12
+ TITLE = %r{<span class="poster-title">([^<]*)</span>}
13
+ DATE = %r{dateshow"><strong>[^<]*</strong>\s*(\d{1,2} [A-Z][a-z]+ \d{4})\s*</span>}
14
+ SHOWTIME = %r{<div class="singlefilmperfs ([^"]*)">(.*?)<input type="hidden" class="perfcat_message"}m
15
+
16
+ # @param [String] html a venue's programme
17
+ def initialize(html)
18
+ @html = html
19
+ end
20
+
21
+ # @return [Array<WtwUk::Internal::Parser::Showtime>] every showtime,
22
+ # including those already passed today
23
+ def showtimes
24
+ @html.split(FILM).drop(1).flat_map do |markup|
25
+ title = markup[TITLE, 1]
26
+ title ? film_showtimes(CGI.unescapeHTML(title), markup) : []
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def film_showtimes(title, markup)
33
+ date = nil
34
+ markup.scan(/#{DATE}|#{SHOWTIME}/o).filter_map do |day, classes, perf|
35
+ if day
36
+ date = Date.strptime(day, '%d %B %Y')
37
+ nil
38
+ elsif date
39
+ Showtime.new(perf, title: title, date: date, classes: classes)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WtwUk
4
+ # @api private
5
+ module Internal
6
+ module Parser
7
+ # Parses one showtime from a venue's programme into performance
8
+ # attributes
9
+ class Showtime
10
+ # Showtime classes and the variants they mean. Others, such as
11
+ # 'audio-des' and 'ccap' (headsets and caption glasses on offer),
12
+ # 'sub-titles' (also on every opera), 'laser', 'strobe-lgt' and
13
+ # 'percatediscountedscreening' (cheap tickets), are not variants.
14
+ CLASSES = {
15
+ 'aslive' => 'arts',
16
+ 'aut' => 'relaxed',
17
+ 'percateeventcinemascreening' => 'arts',
18
+ 'sil' => 'senior',
19
+ 'subtitled' => 'subtitled'
20
+ }.freeze
21
+
22
+ # Event cinema classes are missing from some showtimes
23
+ TITLE_VARIANTS = {
24
+ /\b(?:Exhibition On Screen|National Theatre Live|NT Live|Royal Ballet (?:&|and) Opera|Live On Stage)\b/i =>
25
+ 'arts',
26
+ /\s-\sThe Play\z/i => 'arts',
27
+ /\bQ&A\b/i => 'q&a',
28
+ /\bsubtitle[ds]\b/i => 'subtitled'
29
+ }.freeze
30
+
31
+ THREE_D_CLASS = 'icon-3d'
32
+ THREE_D = /\b3D\b/i
33
+ START = %r{Start time:<span>(\d{1,2}):(\d{2})</span>}
34
+ BOOKING = %r{href="(https://wtwcinemas\.co\.uk/[a-z-]+/booknow/\d+)/?"}
35
+ # Venues differ over hyphens and en dashes in the same title
36
+ EN_DASH = ' – '
37
+ LANGUAGE = /\((#{Cinebase::TitleSanitizer::LANGUAGES.join('|')})\)/i
38
+ TIME_ZONE = 'Europe/London'
39
+
40
+ # @return [Date] the local date of the showtime
41
+ attr_reader :date
42
+
43
+ # @param [String] markup the showtime's markup
44
+ # @param [String] title the film's title as listed
45
+ # @param [Date] date from the showtime's date heading
46
+ # @param [String] classes the showtime's class attribute
47
+ def initialize(markup, title:, date:, classes:)
48
+ @markup = markup
49
+ @title = title.gsub(EN_DASH, ' - ').strip
50
+ @date = date
51
+ @classes = classes.downcase.split
52
+ end
53
+
54
+ # @return [Hash] options for WtwUk::Performance.new
55
+ def to_hash
56
+ {
57
+ booking_url: booking_url,
58
+ dimension: @classes.include?(THREE_D_CLASS) || @title.match?(THREE_D) ? '3d' : '2d',
59
+ festival: Cinebase::Festival.from_title(@title, year: @date.year),
60
+ film_name: TitleSanitizer.new(@title).sanitized,
61
+ film_year: Cinebase::TitleSanitizer.film_year(@title),
62
+ language: @title[LANGUAGE, 1],
63
+ starting_at: starting_at,
64
+ variant: variant
65
+ }
66
+ end
67
+
68
+ private
69
+
70
+ # Showtimes already passed have no link
71
+ def booking_url
72
+ url = @markup[BOOKING, 1]
73
+ url && "#{url}/"
74
+ end
75
+
76
+ def starting_at
77
+ hour, minute = @markup.match(START).captures.map(&:to_i)
78
+ local = Time.utc(@date.year, @date.month, @date.day, hour, minute)
79
+ TZInfo::Timezone.get(TIME_ZONE).local_to_utc(local) { |periods| periods.first }.utc
80
+ end
81
+
82
+ def variant
83
+ from_title = TITLE_VARIANTS.filter_map { |pattern, variant| variant if @title.match?(pattern) }
84
+ (@classes.filter_map { |name| CLASSES[name] } + from_title).uniq
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,38 @@
1
+ module WtwUk
2
+ # Internal utility classes: Do not use
3
+ # @api private
4
+ module Internal
5
+ # Sanitize and standardize film titles
6
+ class TitleSanitizer < Cinebase::TitleSanitizer
7
+ # @!method initialize(title)
8
+ # Constructor
9
+ # @param [String] title a film title
10
+ # @return [WtwUk::Internal::TitleSanitizer]
11
+
12
+ # @!method sanitized
13
+ # sanitized and standardized title
14
+ # @return [String] sanitised title
15
+
16
+ private
17
+
18
+ # strings and regex to be removed
19
+ def remove
20
+ [
21
+ /\ASee It First\s+-\s+/i, # preview
22
+ /\s*-\s*Pat's [^-]+\z/, # Truro's film club strands
23
+ /\s+(?:-\s+)?(?:Subtitled and )?Autism Friendly Screening\z/i, # relaxed screening
24
+ /\s+(?:inc\.?|plus)\s+(?:[\w-]+\s+)*Q&A\z/i # Q&A add-on
25
+ ] + COMMON_REMOVE
26
+ end
27
+
28
+ # regexes and their replacements
29
+ def replace
30
+ {
31
+ /\A(.*) - Royal Ballet (?:&|and) Opera \d{2}-\d{2} Season\z/i => 'Royal Ballet and Opera: ',
32
+ /\A(.*) - Exhibition On Screen\z/i => 'Exhibition on Screen: ',
33
+ /\ANT Live: (.*)/ => 'National Theatre Live: '
34
+ }.merge(COMMON_REPLACE)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WtwUk
4
+ # Internal utility classes: Do not use
5
+ # @api private
6
+ module Internal
7
+ # Reads WTW's WordPress website, built on Jacro's cinema plugin, with a
8
+ # subsite for each venue. No token is needed.
9
+ class Website
10
+ include Http
11
+
12
+ HOME = 'https://wtwcinemas.co.uk'
13
+ # The what's on page's request when a date is chosen
14
+ ACTION = 'jacro_filter_result'
15
+ # The 'All Shows' date, which lists every showtime on sale
16
+ ALL_DATES = 'moredates'
17
+ FILM_TYPE = 'Now Showing'
18
+
19
+ # @param [String] path the venue's subsite, e.g. 'truro'
20
+ # @param [String] location Jacro's cinema id for the venue, e.g. '2'
21
+ # @return [String] every film the venue has on sale, each with every
22
+ # showtime under date headings, however far ahead
23
+ def programme(path, location)
24
+ form = { 'action' => ACTION, 'film_date' => ALL_DATES, 'film_type' => FILM_TYPE, 'cinema_id' => location }
25
+ JSON.parse(post("#{HOME}/#{path}/wp-admin/admin-ajax.php", form)).fetch('html', '').to_s
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,67 @@
1
+ module WtwUk
2
+ # A single screening of a film on the WTW Cinemas website
3
+ class Performance < Cinebase::Performance
4
+ # @!attribute [r] booking_url
5
+ # @return [String, nil] the booking URL on the cinema website
6
+ # @!attribute [r] cinema_name
7
+ # @return [String] the cinema name
8
+ # @!attribute [r] cinema_id
9
+ # @return [String] the cinema id
10
+ # @!attribute [r] dimension
11
+ # @return [String] 2d or 3d
12
+ # @!attribute [r] film_name
13
+ # @return [String] the film name
14
+
15
+ # @!method initialize(options)
16
+ # @param [Hash] options options hash
17
+ # @option options [String] :booking_url (nil) buying url for the screening
18
+ # @option options [String] :cinema_name name of the cinema
19
+ # @option options [String] :cinema_id website id of the cinema
20
+ # @option options [String] :dimension ('2d') dimension of the screening
21
+ # @option options [Cinebase::Festival] :festival (nil) festival edition
22
+ # @option options [String] :film_name name of the film
23
+ # @option options [Integer] :film_year (nil) year from the film's title
24
+ # @option options [String] :language (nil) audio language, e.g. 'Hindi'
25
+ # @option options [Time] :starting_at listed start time of the performance
26
+
27
+ TIME_ZONE = 'Europe/London'.freeze
28
+
29
+ # Performances within an inclusive range of showing dates, from one
30
+ # request: the venue's programme holds every advertised date.
31
+ # @param [String] cinema_id the venue's TapOS site code, e.g. 'PLATRU'
32
+ # @param [Date] from first date (defaults to today in London)
33
+ # @param [Date] to last date (defaults to 13 days after from)
34
+ # @return [Array<WtwUk::Performance>]
35
+ def self.at(
36
+ cinema_id,
37
+ from: TZInfo::Timezone.get(TIME_ZONE).now.to_date,
38
+ to: from + 13
39
+ )
40
+ raise ArgumentError, 'to must not precede from' if to < from
41
+
42
+ cinema = Cinema.new(cinema_id)
43
+ if cinema.name.empty?
44
+ []
45
+ else
46
+ html = WtwUk::Internal::Website.new.programme(cinema.path, cinema.location)
47
+ showtimes = WtwUk::Internal::Parser::Programme.new(html).showtimes
48
+ performances = showtimes.select { |showtime| (from..to).cover?(showtime.date) }.map do |showtime|
49
+ new(showtime.to_hash.merge(cinema_id: cinema.id, cinema_name: cinema.name))
50
+ end
51
+ performances.sort_by(&:starting_at)
52
+ end
53
+ end
54
+
55
+ # @!method showing_on
56
+ # The date of the screening
57
+ # @return [Date]
58
+
59
+ # @!method starting_at
60
+ # UTC time of the screening
61
+ # @return [Time]
62
+
63
+ # @!method variant
64
+ # The kinds of screening (arts, q&a, relaxed, senior, subtitled)
65
+ # @return <Array[String]>
66
+ end
67
+ end
@@ -0,0 +1,6 @@
1
+ # Ruby interface for https://wtwcinemas.co.uk
2
+ # @version 1.0.0
3
+ module WtwUk
4
+ # Gem version
5
+ VERSION = '1.0.0'.freeze
6
+ end
data/lib/wtw_uk.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'cgi/escape'
2
+ require 'json'
3
+
4
+ require 'cinebase'
5
+
6
+ require_relative './wtw_uk/version'
7
+
8
+ require_relative './wtw_uk/internal/http'
9
+ require_relative './wtw_uk/internal/website'
10
+ require_relative './wtw_uk/internal/title_sanitizer'
11
+ require_relative './wtw_uk/internal/parser/showtime'
12
+ require_relative './wtw_uk/internal/parser/programme'
13
+
14
+ require_relative './wtw_uk/cinema'
15
+ require_relative './wtw_uk/performance'
16
+
17
+ # wtw_uk gem
18
+ module WtwUk
19
+ end