auntie 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +49 -0
- data/LICENSE +20 -0
- data/README.md +39 -0
- data/Rakefile +24 -0
- data/bin/news +4 -0
- data/bin/radio +51 -0
- data/bin/sport +4 -0
- data/bin/tv +45 -0
- data/bin/weather +23 -0
- data/features/location.feature +8 -0
- data/features/news.feature +8 -0
- data/features/radio.feature +8 -0
- data/features/sport.feature +8 -0
- data/features/step_definitions/location_steps.rb +7 -0
- data/features/step_definitions/radio_steps.rb +1 -0
- data/features/step_definitions/tv_steps.rb +1 -0
- data/features/step_definitions/weather_steps.rb +6 -0
- data/features/support/env.rb +15 -0
- data/features/tv.feature +8 -0
- data/features/weather.feature +8 -0
- data/lib/auntie.rb +16 -0
- data/lib/bbc/location.rb +44 -0
- data/lib/bbc/news.rb +28 -0
- data/lib/bbc/now_next.rb +93 -0
- data/lib/bbc/schedule.rb +53 -0
- data/lib/bbc/shell/characters.rb +68 -0
- data/lib/bbc/shell/colors.rb +39 -0
- data/lib/bbc/shell/describe_time.rb +20 -0
- data/lib/bbc/sport.rb +33 -0
- data/lib/bbc/version.rb +7 -0
- data/lib/bbc/weather.rb +98 -0
- data/scratch +9 -0
- data/spec/bbc/location_spec.rb +45 -0
- data/spec/bbc/news_spec.rb +43 -0
- data/spec/bbc/now_next_spec.rb +53 -0
- data/spec/bbc/schedule_spec.rb +56 -0
- data/spec/bbc/sport_spec.rb +35 -0
- data/spec/bbc/version_spec.rb +18 -0
- data/spec/bbc/weather_spec.rb +41 -0
- data/spec/fixtures/3dayforecast.json +149 -0
- data/spec/fixtures/3hourlyforecast.json +265 -0
- data/spec/fixtures/location.json +12 -0
- data/spec/fixtures/news.json +31 -0
- data/spec/fixtures/now_next_radio.json +7767 -0
- data/spec/fixtures/now_next_tv.json +3471 -0
- data/spec/fixtures/schedule_radio_today.json +939 -0
- data/spec/fixtures/schedule_radio_tomorrow.json +941 -0
- data/spec/fixtures/schedule_radio_yesterday.json +1118 -0
- data/spec/fixtures/schedule_tv.json +1695 -0
- data/spec/fixtures/sport.json +38 -0
- data/spec/spec_helper.rb +13 -0
- metadata +170 -0
data/lib/bbc/news.rb
ADDED
@@ -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
|
data/lib/bbc/now_next.rb
ADDED
@@ -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
|
data/lib/bbc/schedule.rb
ADDED
@@ -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
|
data/lib/bbc/sport.rb
ADDED
@@ -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
|
data/lib/bbc/version.rb
ADDED
data/lib/bbc/weather.rb
ADDED
@@ -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
|