├── Dockerfile ├── config.ru ├── api └── app.rb ├── Gemfile ├── lib ├── connector.rb └── parser.rb ├── README.md └── Gemfile.lock /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.7.0 2 | WORKDIR /app 3 | COPY . /app 4 | RUN bundle install 5 | 6 | ENV SENDER_ID="" 7 | CMD puma -p 3000 8 | EXPOSE 3000 9 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative './api/app' 4 | 5 | mapping = { '/' => Api } 6 | 7 | run Rack::URLMap.new(mapping) 8 | -------------------------------------------------------------------------------- /api/app.rb: -------------------------------------------------------------------------------- 1 | require 'syro' 2 | 3 | require_relative '../lib/connector.rb' 4 | 5 | Api = Syro.new do 6 | post do 7 | response = Connector.waiting_time 8 | 9 | res.json(response.to_json) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 3 | 4 | gem 'http' 5 | gem 'puma' 6 | gem 'racksh' 7 | gem 'syro' 8 | 9 | group 'development' do 10 | gem 'pry' 11 | end 12 | -------------------------------------------------------------------------------- /lib/connector.rb: -------------------------------------------------------------------------------- 1 | require_relative 'parser' 2 | require 'http' 3 | 4 | class Connector 5 | SENDER_ID = ENV.fetch('SENDER_ID') 6 | URI = "http://www.wienerlinien.at/ogd_realtime/monitor?rbl=361&activateTrafficInfo=stoerunglang&sender=#{SENDER_ID}".freeze 7 | 8 | def self.waiting_time 9 | payload = get 10 | Parser.new(payload).build_response 11 | end 12 | 13 | def self.get 14 | HTTP.get(URI).to_s 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tram Time 2 | this is a tiny ruby server, to count down the tram arrival time for me. 3 | It's connected to Alexa via personal skill. 4 | 5 | # Run 6 | `docker build tram_time:dev .` 7 | 8 | `docker run -d -p 80:3000 tram_time:dev` 9 | 10 | `curl -X POST http://localhost` 11 | 12 | 13 | ## TODOs 14 | 15 | - [ ] Write specs. 16 | - [ ] Add nginx conf 17 | - [ ] Add more info to the returned response. 18 | - [ ] Add slots/locations as a setup. 19 | - [ ] Add the Alexa json model. 20 | 21 | ## Epilogue 22 | I may not work on any of the above tasks at all, the code works blazningly amazing, alexa tells me what I want every morning, 23 | and that's super cool. I wanted to add more features and make this works for everyone there, but I don't have time... 24 | you can reach me however for any questions 😘 25 | -------------------------------------------------------------------------------- /lib/parser.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | class Parser 4 | def initialize(payload) 5 | self.departure_times = get_departure_times(JSON.parse(payload)) 6 | end 7 | 8 | def build_response 9 | { 10 | version: '1.0', 11 | response: { 12 | outputSpeech: { 13 | type: 'PlainText', 14 | text: "Next tram will be here in #{count_down.first} minutes, \ 15 | And the one after will be here in #{count_down[1]} minutes, \ 16 | later on after #{count_down.last} minutes" 17 | } 18 | } 19 | } 20 | end 21 | 22 | private 23 | 24 | attr_accessor :departure_times 25 | 26 | def get_departure_times(payload) 27 | payload.dig('data', 'monitors', 0, 'lines', 0, 'departures', 'departure') 28 | end 29 | 30 | def count_down 31 | [ 32 | departure_times.dig(0, 'departureTime', 'countdown'), 33 | departure_times.dig(1, 'departureTime', 'countdown'), 34 | departure_times.dig(2, 'departureTime', 'countdown') 35 | ] 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.8.5) 5 | public_suffix (>= 2.0.2, < 6.0) 6 | coderay (1.1.3) 7 | domain_name (0.5.20190701) 8 | unf (>= 0.0.5, < 1.0.0) 9 | ffi (1.15.5) 10 | ffi-compiler (1.0.1) 11 | ffi (>= 1.0.0) 12 | rake 13 | http (5.1.1) 14 | addressable (~> 2.8) 15 | http-cookie (~> 1.0) 16 | http-form_data (~> 2.2) 17 | llhttp-ffi (~> 0.4.0) 18 | http-cookie (1.0.5) 19 | domain_name (~> 0.5) 20 | http-form_data (2.3.0) 21 | llhttp-ffi (0.4.0) 22 | ffi-compiler (~> 1.0) 23 | rake (~> 13.0) 24 | method_source (1.0.0) 25 | nio4r (2.7.0) 26 | pry (0.14.2) 27 | coderay (~> 1.1) 28 | method_source (~> 1.0) 29 | public_suffix (5.0.3) 30 | puma (6.4.2) 31 | nio4r (~> 2.0) 32 | rack (3.0.9.1) 33 | rack-test (2.1.0) 34 | rack (>= 1.3) 35 | racksh (1.0.1) 36 | rack (>= 1.0) 37 | rack-test (>= 0.5) 38 | rake (13.0.6) 39 | seg (1.2.0) 40 | syro (3.2.1) 41 | rack (>= 1.6.0) 42 | seg 43 | unf (0.1.4) 44 | unf_ext 45 | unf_ext (0.0.8.2) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | http 52 | pry 53 | puma 54 | racksh 55 | syro 56 | 57 | BUNDLED WITH 58 | 2.4.18 59 | --------------------------------------------------------------------------------