auntie 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +49 -0
  4. data/LICENSE +20 -0
  5. data/README.md +39 -0
  6. data/Rakefile +24 -0
  7. data/bin/news +4 -0
  8. data/bin/radio +51 -0
  9. data/bin/sport +4 -0
  10. data/bin/tv +45 -0
  11. data/bin/weather +23 -0
  12. data/features/location.feature +8 -0
  13. data/features/news.feature +8 -0
  14. data/features/radio.feature +8 -0
  15. data/features/sport.feature +8 -0
  16. data/features/step_definitions/location_steps.rb +7 -0
  17. data/features/step_definitions/radio_steps.rb +1 -0
  18. data/features/step_definitions/tv_steps.rb +1 -0
  19. data/features/step_definitions/weather_steps.rb +6 -0
  20. data/features/support/env.rb +15 -0
  21. data/features/tv.feature +8 -0
  22. data/features/weather.feature +8 -0
  23. data/lib/auntie.rb +16 -0
  24. data/lib/bbc/location.rb +44 -0
  25. data/lib/bbc/news.rb +28 -0
  26. data/lib/bbc/now_next.rb +93 -0
  27. data/lib/bbc/schedule.rb +53 -0
  28. data/lib/bbc/shell/characters.rb +68 -0
  29. data/lib/bbc/shell/colors.rb +39 -0
  30. data/lib/bbc/shell/describe_time.rb +20 -0
  31. data/lib/bbc/sport.rb +33 -0
  32. data/lib/bbc/version.rb +7 -0
  33. data/lib/bbc/weather.rb +98 -0
  34. data/scratch +9 -0
  35. data/spec/bbc/location_spec.rb +45 -0
  36. data/spec/bbc/news_spec.rb +43 -0
  37. data/spec/bbc/now_next_spec.rb +53 -0
  38. data/spec/bbc/schedule_spec.rb +56 -0
  39. data/spec/bbc/sport_spec.rb +35 -0
  40. data/spec/bbc/version_spec.rb +18 -0
  41. data/spec/bbc/weather_spec.rb +41 -0
  42. data/spec/fixtures/3dayforecast.json +149 -0
  43. data/spec/fixtures/3hourlyforecast.json +265 -0
  44. data/spec/fixtures/location.json +12 -0
  45. data/spec/fixtures/news.json +31 -0
  46. data/spec/fixtures/now_next_radio.json +7767 -0
  47. data/spec/fixtures/now_next_tv.json +3471 -0
  48. data/spec/fixtures/schedule_radio_today.json +939 -0
  49. data/spec/fixtures/schedule_radio_tomorrow.json +941 -0
  50. data/spec/fixtures/schedule_radio_yesterday.json +1118 -0
  51. data/spec/fixtures/schedule_tv.json +1695 -0
  52. data/spec/fixtures/sport.json +38 -0
  53. data/spec/spec_helper.rb +13 -0
  54. metadata +170 -0
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ class News
4
+ def initialize(io=STDOUT)
5
+ @io = io
6
+ end
7
+
8
+ def load
9
+ cols = `stty size`.split(' ')[1].to_i
10
+
11
+ @io.puts 'BBC News Headlines'
12
+ data['entries'].each { |news_item|
13
+ @io.puts news_item['headline'][0..cols-1]
14
+ }
15
+ end
16
+
17
+ private
18
+
19
+ def data
20
+ begin
21
+ raw = open('http://www.bbc.co.uk/news/10284448/ticker.sjson', 'UserAgent' => AUNTIE::USER_AGENT).read
22
+ JSON.parse(raw)
23
+ rescue
24
+ @io.puts "Unable to download news"
25
+ exit
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,93 @@
1
+ # encoding: utf-8
2
+
3
+ class NowNext
4
+ def initialize(io=STDIN)
5
+ @io = io
6
+ end
7
+
8
+ def tv_now
9
+ @fmt = "%-18s %s"
10
+ load 'tv'
11
+
12
+ on_now
13
+ end
14
+
15
+ def tv_next
16
+ @fmt = "%-18s %s"
17
+ load 'tv'
18
+
19
+ on_next
20
+ end
21
+
22
+ def radio_now
23
+ @fmt = "%-32s %s"
24
+ load 'radio'
25
+
26
+ on_now
27
+ end
28
+
29
+ def radio_next
30
+ @fmt = "%-32s %s"
31
+ load 'radio'
32
+
33
+ on_next
34
+ end
35
+
36
+ private
37
+
38
+ Programme = Struct.new(:channel, :title, :starts, :starts_in)
39
+
40
+ def load medium
41
+ begin
42
+ raw = open("http://www.bbc.co.uk/iplayer/ion/multinownext/service_type/#{medium}/simulcast_only/1/format/json", 'UserAgent' => AUNTIE::USER_AGENT).read
43
+ @data = JSON.parse(raw)
44
+ rescue
45
+ @io.puts "Unable to download #{medium} schedules"
46
+ exit
47
+ end
48
+ end
49
+
50
+ def on_now
51
+ @data['blocklist'].each { |e|
52
+ channel = format_channel e['title']
53
+ programme = e['now'][0]['episode']['passionsite_title'] rescue next
54
+
55
+ @io.puts sprintf @fmt, channel, programme
56
+ }
57
+ end
58
+
59
+ def on_next
60
+ programmes = []
61
+
62
+ first = 9
63
+ second = 0
64
+
65
+ @data['blocklist'].each { |e|
66
+ p = Programme.new
67
+ p.channel = format_channel e['title']
68
+
69
+ p.title = e['next'][0]['episode']['passionsite_title'] rescue ''
70
+ p.starts = Time.parse(e['next'][0]['start_time_iso']) rescue ''
71
+
72
+ #next_start = starts.strftime("%H:%M")
73
+ p.starts_in = how_long_between(time_now, p.starts)
74
+
75
+ second = p.channel.length+3 if p.channel.length > second
76
+
77
+ programmes << p
78
+ }
79
+
80
+ programmes.sort_by! { |p| p.starts }
81
+
82
+ programmes.each { |p| @io.puts sprintf "%-#{first}s %-#{second}s %s", p.starts_in, p.channel, p.title }
83
+
84
+ end
85
+
86
+ def format_channel name
87
+ name.gsub(/^BBC | (London|England|Channel)/,'')
88
+ end
89
+
90
+ def time_now
91
+ Time.now
92
+ end
93
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ # Helpful urls
4
+ #
5
+ # http://www.bbc.co.uk/programmes/developers
6
+ # http://www.bbc.co.uk/ontologies/programmes/2009-09-07.shtml
7
+
8
+ class Schedule
9
+ def initialize(io=STDOUT)
10
+ @io = io
11
+ end
12
+
13
+ def load channel
14
+ station = channel[:id]
15
+ region = channel[:region] ||= ''
16
+ period = channel[:period] ||= ''
17
+
18
+ url = "http://www.bbc.co.uk/#{station}/programmes/schedules#{region}#{period}.json"
19
+
20
+ raw = open(url, 'UserAgent' => AUNTIE::USER_AGENT).read
21
+ data = JSON.parse(raw)
22
+
23
+ list data
24
+ end
25
+
26
+ def list data
27
+ now = time_now
28
+
29
+ data['schedule']['day']['broadcasts'].each do |e|
30
+
31
+ ends = Time.parse(e['end'])
32
+
33
+ title = e['programme']['display_titles']['title']
34
+ #synopsis = e['programme']['short_synopsis']
35
+
36
+ starts = Time.parse(e['start'])
37
+
38
+ starts_at = starts.strftime("%H:%M")
39
+ #starts_at = starts.strftime("%I:%M%P")
40
+ desc = "#{starts_at} #{title}"
41
+
42
+ if (starts < now) && (ends > now)
43
+ desc = light_green desc
44
+ end
45
+
46
+ @io.puts desc
47
+ end
48
+ end
49
+
50
+ def time_now
51
+ Time.now
52
+ end
53
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+
3
+ #http://www.utf8-chartable.de/unicode-utf8-table.pl
4
+
5
+ module ShellCharacters
6
+
7
+ def west
8
+ "\xe2\x86\x90"
9
+ end
10
+
11
+ def east
12
+ "\xe2\x86\x92"
13
+ end
14
+
15
+ def south
16
+ "\xe2\x86\x93"
17
+ end
18
+
19
+ def north
20
+ "\xe2\x86\x91"
21
+ end
22
+
23
+ def north_west
24
+ "\xe2\x86\x96"
25
+ end
26
+
27
+ def north_east
28
+ "\xe2\x86\x97"
29
+ end
30
+
31
+ def south_west
32
+ "\xe2\x86\x99"
33
+ end
34
+
35
+ def south_east
36
+ "\xe2\x86\x98"
37
+ end
38
+
39
+ def degrees_c
40
+ "\xC2\xB0C" #Shell escaped °C
41
+ end
42
+
43
+ def square_block
44
+ "\xe2\x96\x88"
45
+ end
46
+
47
+ def symbol_for_compass(direction)
48
+ case direction
49
+ when 'N' then north
50
+ when 'NNE' then north
51
+ when 'NE' then north_east
52
+ when 'ENE' then east
53
+ when 'E' then east
54
+ when 'ESE' then east
55
+ when 'SE' then south_east
56
+ when 'SSE' then south
57
+ when 'S' then south
58
+ when 'SSW' then south
59
+ when 'SW' then south_west
60
+ when 'WSW' then west
61
+ when 'W' then west
62
+ when 'WNW' then west
63
+ when 'NW' then north_west
64
+ when 'NNW' then north
65
+ else north
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+
3
+ # Useful list of colour codes
4
+ # http://misc.flogisoft.com/bash/tip_colors_and_formatting
5
+
6
+ # And alternatives
7
+ # http://stackoverflow.com/questions/1108767/terminal-color-in-ruby
8
+
9
+ def paint txt, color
10
+ "\033[#{color}m#{txt}\033[0m"
11
+ end
12
+
13
+ def green txt
14
+ paint txt, 32
15
+ end
16
+
17
+ def red txt
18
+ paint txt, 31
19
+ end
20
+
21
+ def light_green txt
22
+ paint txt, 92
23
+ end
24
+
25
+ def yellow txt
26
+ paint txt, 33
27
+ end
28
+
29
+ def cyan txt
30
+ paint txt, 36
31
+ end
32
+
33
+ def blue txt
34
+ paint txt, 34
35
+ end
36
+
37
+ def white txt
38
+ paint txt, 37
39
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ def how_long_between past, future
4
+ a = (future-past).to_i
5
+
6
+ case a
7
+ when -10000000..0 then "On now"
8
+ when 0 then 'Now!'
9
+ when 1 then 'A second'
10
+ when 2..59 then a.to_s+' secs'
11
+ when 60..119 then 'A min' #120 = 2 minutes
12
+ when 120..3540 then (a/60).to_i.to_s+' mins'
13
+ when 3541..7100 then 'An hour' # 3600 = 1 hour
14
+ when 7101..82800 then ((a+99)/3600).to_i.to_s+' hours'
15
+ when 82801..172000 then 'A day' # 86400 = 1 day
16
+ when 172001..518400 then ((a+800)/(60*60*24)).to_i.to_s+' days'
17
+ when 518400..1036800 then 'A week'
18
+ else ((a+180000)/(60*60*24*7)).to_i.to_s+' weeks'
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ class Sport
4
+ def initialize(io=STDOUT)
5
+ @io = io
6
+ end
7
+
8
+ def headlines
9
+ data['entries'].each { |item|
10
+ prompt = yellow item['prompt'].capitalize.ljust(22)
11
+
12
+ headline = item['headline']
13
+ @io.puts prompt+headline
14
+ }
15
+ end
16
+
17
+ private
18
+
19
+ def url
20
+ 'http://polling.bbc.co.uk/sport/0/16189337/ticker.sjson'
21
+ end
22
+
23
+ def data
24
+ begin
25
+ raw = open(url, 'UserAgent' => AUNTIE::USER_AGENT).read
26
+ JSON.parse(raw)
27
+ rescue
28
+ @io.puts "Unable to download sport"
29
+ exit
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ module AUNTIE
4
+ VERSION = '0.1.0'
5
+ NAME = 'auntie'
6
+ USER_AGENT = "#{NAME}-#{VERSION}"
7
+ end
@@ -0,0 +1,98 @@
1
+ # encoding: utf-8
2
+
3
+ class Weather
4
+ include ShellCharacters
5
+
6
+ attr_reader :base_url
7
+
8
+ def initialize(location, io=STDOUT)
9
+ @io = io
10
+ @base_url = "http://open.live.bbc.co.uk/weather/feeds/en/#{location}"
11
+ end
12
+
13
+ def hourly
14
+ feed = load("#{base_url}/3hourlyforecast.json")
15
+
16
+ location = feed['forecastContent']['location']['locationName']
17
+
18
+ @io.puts "\nThe next 24 hours in #{location}\n\n"
19
+ @io.puts "Day Time Weather Max#{degrees_c} Wind"
20
+
21
+ feed['forecastContent']['forecasts'].each { |e|
22
+
23
+ day = e['dayName'].ljust(10)
24
+ time = e['timeSlot'].ljust(7)
25
+ desc = e['weatherType'].ljust(19)
26
+
27
+ temp = e['temperature']['centigrade'].to_s || '?'
28
+ temp = "#{temp}#{degrees_c}".ljust(6)
29
+
30
+ wind = e['wind']['directionDesc']
31
+ wind_dir = e['wind']['direction']
32
+ wind_spd = e['wind']['windspeed']['mph'] || '?'
33
+ wind_spd = "#{wind_spd}mph".ljust(5)
34
+
35
+ #visibility = e['visibility']
36
+ #millibars = e['pressureMillibars']
37
+ #humidity = e['humidityPercent']
38
+ #temp_colour = temp_to_color(temp.to_i)
39
+
40
+ @io.puts "#{yellow day} #{time} #{desc} #{temp} #{wind_spd} #{wind}"
41
+ }
42
+ @io.puts "\n"
43
+ end
44
+
45
+ def daily
46
+ feed = load("#{base_url}/3dayforecast.json")
47
+
48
+ location = feed['forecastContent']['location']['locationName']
49
+
50
+ @io.puts "\nThe next 3 days in #{location}\n\n"
51
+ @io.puts "Day Time Weather Max#{degrees_c} Wind"
52
+
53
+ feed['forecastContent']['forecasts'].each { |e|
54
+ day = sprintf "%-10s", e['dayName']
55
+
56
+ d_weather = e['day']['weatherType']
57
+ d_weather = sprintf "%-12s", d_weather unless d_weather.nil?
58
+
59
+ d_temp = e['day']['maxTemperature']['centigrade']
60
+ d_temp = "#{d_temp}\xC2\xB0C" unless d_temp.nil?
61
+
62
+ d_wind = e['day']['wind']['directionDesc']
63
+ d_wind_spd = e['day']['wind']['windspeed']['mph']
64
+ d_wind_spd = "#{d_wind_spd}mph" unless d_wind_spd.nil?
65
+
66
+ day_desc = sprintf "%-17s %-6s %-5s %-20s", d_weather, d_temp, d_wind_spd, d_wind
67
+
68
+ n_weather = e['night']['weatherType']
69
+ n_temp = e['night']['minTemperature']['centigrade']
70
+ n_temp = "#{n_temp}\xC2\xB0C" unless n_temp.nil?
71
+
72
+ night_desc = sprintf "%-12s %-3s", n_weather, n_temp
73
+
74
+ @io.puts "#{yellow day} #{day_desc} #{cyan 'night'} #{white night_desc}"
75
+ }
76
+ end
77
+
78
+ private
79
+
80
+ def load(url)
81
+ begin
82
+ raw = open(url, 'UserAgent' => AUNTIE::USER_AGENT).read
83
+ JSON.parse(raw)
84
+ rescue
85
+ @io.puts "Unable to download the weather"
86
+ exit
87
+ end
88
+ end
89
+
90
+ #def temp_to_color(temp)
91
+ # case temp
92
+ # when -100..0 then blue(square_block)
93
+ # when 0..10 then yellow(square_block)
94
+ # else red(square_block)
95
+ # end
96
+ #end
97
+
98
+ end