auntie 0.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.
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