class NSClient

Attributes

last_received_corrected_xml[RW]
last_received_raw_xml[RW]
password[RW]
username[RW]

Public Class Methods

new(username, password) click to toggle source
# File lib/ns_client.rb, line 41
def initialize(username, password)
  @username = username
  @password = password
  @prices_url = PricesUrl.new('https://webservices.ns.nl/ns-api-prijzen-v3')
  @last_received_raw_xml = ''
  @last_received_corrected_xml = ''
end

Public Instance Methods

disruption_url(query) click to toggle source
# File lib/ns_client.rb, line 213
def disruption_url(query)
  return "https://webservices.ns.nl/ns-api-storingen?station=#{query}" if query

  'https://webservices.ns.nl/ns-api-storingen?actual=true'
end
disruptions(query = nil) click to toggle source
# File lib/ns_client.rb, line 57
def disruptions(query = nil)
  response_xml = get_xml(disruption_url(query))
  raise_error_when_response_is_error(response_xml)
  parse_disruptions(response_xml)
end
get_xml(url) click to toggle source
# File lib/ns_client.rb, line 196
def get_xml(url)
  response = RestClient::Request.new(url: url, user: username, password: password, method: :get).execute
  @last_received_raw_xml = response.body
  @last_received_corrected_xml = remove_unwanted_whitespace(@last_received_raw_xml)
  begin
    Nokogiri.XML(@last_received_corrected_xml) do |config|
      config.options = Nokogiri::XML::ParseOptions::STRICT
    end
  rescue Nokogiri::XML::SyntaxError => e
    raise UnparseableXMLError, e
  end
end
parse_disruptions(response_xml) click to toggle source
# File lib/ns_client.rb, line 153
def parse_disruptions(response_xml)
  result = { planned: [], unplanned: [] }
  (response_xml / '/Storingen').each do |disruption|
    (disruption / 'Ongepland/Storing').each do |unplanned|
      result[:unplanned] << parse_unplanned_disruption(unplanned)
    end

    (disruption / 'Gepland/Storing').each do |planned|
      result[:planned] << parse_planned_disruption(planned)
    end
  end
  result
end
parse_planned_disruption(disruption) click to toggle source
# File lib/ns_client.rb, line 178
def parse_planned_disruption(disruption)
  result = PlannedDisruption.new
  result.id = (disruption / './id').text
  result.trip = (disruption / './Traject').text
  result.reason = (disruption / './Reden').text
  result.advice = (disruption / './Advies').text
  result.message = (disruption / './Bericht').text
  result.cause = (disruption / './Oorzaak').text
  result
end
parse_prices(response_xml) click to toggle source
# File lib/ns_client.rb, line 85
def parse_prices(response_xml)
  prices_response = PricesResponse.new
  (response_xml / '/VervoerderKeuzes/VervoerderKeuze').each do |transporter|
    prices_response.tariff_units = (transporter / './Tariefeenheden').text.to_i

    (transporter / 'ReisType').each do |travel_type|
      prices = parse_travel_type(travel_type)

      name = travel_type.attr('name')
      prices_response.products[name] = prices
    end
  end
  prices_response
end
parse_station(station) click to toggle source
# File lib/ns_client.rb, line 124
def parse_station(station)
  s = Station.new
  s.code = parse_station_field(station, './Code')
  s.type = parse_station_field(station, './Type')
  s.country = parse_station_field(station, './Land')
  s.short_name = parse_station_field(station, './Namen/Kort')
  s.name = parse_station_field(station, './Namen/Middel')
  s.long_name = parse_station_field(station, './Namen/Lang')
  s.lat = parse_station_field(station, './Lat')
  s.long = parse_station_field(station, './Lon')
  s.uiccode = parse_station_field(station, './UICCode')
  s
end
parse_station_field(station, field) click to toggle source
# File lib/ns_client.rb, line 138
def parse_station_field(station, field)
  (station / field).text
end
parse_stations(response_xml) click to toggle source
# File lib/ns_client.rb, line 116
def parse_stations(response_xml)
  result = []
  (response_xml / '/Stations/Station').each do |station|
    result << parse_station(station)
  end
  result
end
parse_stations_as_map(response_xml) click to toggle source
# File lib/ns_client.rb, line 142
def parse_stations_as_map(response_xml)
  result = {}
  (response_xml / '/Stations/Station').each do |station|
    code = (station / './Code').text
    name = (station / './Namen/Middel').text
    country = (station / './Land').text
    result[code] = [name, country]
  end
  result
end
parse_travel_type(travel_type) click to toggle source
# File lib/ns_client.rb, line 100
def parse_travel_type(travel_type)
  prices = []

  (travel_type / 'ReisKlasse').each do |travel_class|
    (travel_class / 'Korting/Kortingsprijs').each do |price_element|
      product_price = ProductPrice.new
      product_price.discount = price_element.attr('name')
      product_price.train_class = travel_class.attr('klasse')
      product_price.amount = price_element.attr('prijs').tr(',', '.').to_f
      prices << product_price
    end
  end

  prices
end
parse_unplanned_disruption(disruption) click to toggle source
# File lib/ns_client.rb, line 167
def parse_unplanned_disruption(disruption)
  result = UnplannedDisruption.new
  result.id = (disruption / './id').text
  result.trip = (disruption / './Traject').text
  result.reason = (disruption / './Reden').text
  result.message = (disruption / './Bericht').text
  result.datetime_string = (disruption / './Datum').text
  result.cause = (disruption / './Oorzaak').text
  result
end
prices(opts = { from: nil, to: nil, via: nil, date: nil }) click to toggle source
# File lib/ns_client.rb, line 63
def prices(opts = { from: nil, to: nil, via: nil, date: nil })
  validate_prices(opts)
  response_xml = get_xml(@prices_url.url(opts))
  raise_error_when_response_is_error(response_xml)
  parse_prices(response_xml)
end
raise_error_when_response_is_error(xdoc) click to toggle source
# File lib/ns_client.rb, line 189
def raise_error_when_response_is_error(xdoc)
  (xdoc / '/error').each do |error|
    message = (error / './message').text
    raise InvalidStationNameError, message
  end
end
remove_unwanted_whitespace(content) click to toggle source
# File lib/ns_client.rb, line 209
def remove_unwanted_whitespace(content)
  content.gsub %r{<\s*(/?)\s*?([a-zA-Z0-9]*)\s*([a-zA-Z0-9]*)\s*>}, '<\1\2\3>'
end
stations() click to toggle source
# File lib/ns_client.rb, line 49
def stations
  parse_stations(get_xml('https://webservices.ns.nl/ns-api-stations-v2'))
end
stations_short() click to toggle source
# File lib/ns_client.rb, line 53
def stations_short
  parse_stations_as_map(get_xml('https://webservices.ns.nl/ns-api-stations-v2'))
end
validate_price_parameters(opts) click to toggle source
# File lib/ns_client.rb, line 70
def validate_price_parameters(opts)
  raise MissingParameter, 'from and to station is required' if opts[:from].nil? && opts[:to].nil?
  raise MissingParameter, 'from station is required' unless opts[:from]
  raise MissingParameter, 'to station is required' unless opts[:to]
end
validate_prices(opts) click to toggle source
# File lib/ns_client.rb, line 76
def validate_prices(opts)
  validate_price_parameters(opts)

  return unless opts[:from] == opts[:to]

  raise SameDestinationError,
        "from (#{opts[:from]}) and to (#{opts[:to]}) parameters should not be equal"
end