nowtv 0.0.2 → 0.0.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0a4da7370a94335359641039bfc869774d5a7ed
4
- data.tar.gz: b50ee77e4e6f01f99dc70f4036734c4e08078728
3
+ metadata.gz: 03bbfba04c00fa825326e9dbc7ff974071597737
4
+ data.tar.gz: 225989b95cd8825f3a3b36739a153ecd356f2cd7
5
5
  SHA512:
6
- metadata.gz: c2a8b904d2dcdd1d034c0179e51fdbbe19170283fb00bb7caf7fa4cb46fd2925fda829b5a7056940a375e628f27cc944e31c64037ea717d0af2dc14a2c39774c
7
- data.tar.gz: baa8be89893c8fbd125f51e6486a6d3a547e04f8ab37b0b9d2a56840e594574ae5c744aec738562080ac587ba1e7d22254ab01ea1b4d3204fd639193397f9d08
6
+ metadata.gz: 7d34f6f74e74938b6b6f42b5f22172882296c5b51971639d336ca0268a44cf9eea4a044bc00268f7921bbb44647a96b4a8001f16df7f288a24e77fc267c21897
7
+ data.tar.gz: 3cb522316e2b1df5fdb2cf102f88e4a5f49db86e42ec20bf29d94788dc2abdef3685e072d5541d8ff052e3f61e8b1b944d2efd7310581dcc7c4f60f94c4cf00c
@@ -1,3 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 1.9.3
3
4
  - 2.0.0
5
+ - 2.1.0
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Nowtv
2
2
 
3
3
  [![Build Status](https://travis-ci.org/dtan4/nowtv.png?branch=master)](https://travis-ci.org/dtan4/nowtv)
4
+ [![Coverage Status](https://coveralls.io/repos/dtan4/nowtv/badge.png?branch=master)](https://coveralls.io/r/dtan4/nowtv?branch=master)
5
+ [![Code Climate](https://codeclimate.com/github/dtan4/nowtv.png)](https://codeclimate.com/github/dtan4/nowtv)
4
6
 
5
7
  Show current TV programs
6
8
 
data/bin/nowtv CHANGED
@@ -1,20 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
4
-
5
3
  require 'nowtv'
6
4
 
7
5
  CONFIGURE_PATH = ENV["HOME"] + '/.nowtv'
6
+ USAGE = "USAGE: nowtv [prefecture]"
8
7
 
9
- region_code =
8
+ prefecture =
10
9
  File.exists?(CONFIGURE_PATH) ? open(CONFIGURE_PATH).read.lines[0].strip : 'tokyo'
11
10
 
12
11
  if ARGV.length > 1
13
- $stderr.puts 'Too many arguments.'
12
+ $stderr.puts USAGE
13
+ exit 1
14
14
  elsif ARGV.length == 1
15
- region_code = ARGV[0]
15
+ prefecture = ARGV[0]
16
16
  end
17
17
 
18
+ region_code = Nowtv::Region.get_region_id(prefecture)
18
19
  client = Nowtv::Client.new
19
20
  programs = client.get_program_list(region_code)
20
21
 
@@ -1,5 +1,6 @@
1
1
  require "nowtv/version"
2
2
  require "nowtv/client"
3
+ require "nowtv/region"
3
4
 
4
5
  module Nowtv
5
6
  # something
@@ -6,56 +6,58 @@ require 'nkf'
6
6
 
7
7
  module Nowtv
8
8
  class Client
9
- API_URL = 'http://asp.tvguide.or.jp/api/broadcasting?region_code='
10
- REGION_URL = 'http://asp.tvguide.or.jp/api/regions'
11
-
12
- def get_program_list(region)
13
- programs = get_programs(region)
14
-
15
- unless programs.length > 1
16
- region_code_by_name = get_region_code(region)
17
-
18
- unless region_code_by_name
19
- $stderr.puts 'Failed to get programs!'
20
- return nil
21
- end
22
-
23
- programs = get_programs(region_code_by_name)
24
- end
9
+ API_URL = 'http://www.tvguide.or.jp/TXML301PG.php?type=TVG&regionId='
25
10
 
11
+ def get_program_list(region_id)
12
+ programs = get_programs(region_id)
26
13
  restruct_program_list(programs)
14
+ rescue
15
+ raise ParseError, "Failed to parse program data"
27
16
  end
28
17
 
29
- def get_programs(region_code)
30
- url = API_URL + region_code
31
- JSON.parse(open(url).read.sub(/^\(/, '').sub(/\)$/, ''))['programs']
32
- rescue
33
- []
18
+ private
19
+
20
+ def get_programs(region_id)
21
+ url = API_URL + region_id.to_s
22
+ JSON.parse(open(url).read)["ProgramScheduleInfomartion"]["MediaLocation"]["StationLocation"]
34
23
  end
35
24
 
36
25
  def restruct_program_list(programs)
37
26
  programs.map do |program|
27
+ info = program["ProgramInformation"]
28
+
38
29
  {
39
- station: NKF.nkf("-wZ0", program["station_name"]),
40
- title: NKF.nkf("-wZ0", program["title"]).gsub(" ", " "),
41
- start_time: Time.parse(program["start"]).strftime("%H:%M"),
42
- end_time: Time.parse(program["end"]).strftime("%H:%M")
30
+ station: half_width(program["stationDispName"]),
31
+ title: half_width(info["programTitle"]),
32
+ start_time: parse_datetime(info["startDateTime"]),
33
+ end_time: parse_datetime(info["endDateTime"])
43
34
  }
44
35
  end
45
36
  end
46
37
 
47
- def get_region_list
48
- regions = JSON.parse(open(REGION_URL).read.sub(/^\(/, '').sub(/\)$/, ''))['regions']
49
- result = {}
50
- regions.each { |region| result[region["name"].to_sym] = region["code"] }
51
- result
52
- rescue
53
- {}
38
+ def half_width(str)
39
+ NKF.nkf("-wZ0", str).gsub(" ", " ")
40
+ end
41
+
42
+ def parse_datetime(datetime)
43
+ date, time = datetime.split(" ")
44
+ hour, minute = time.split(":").map(&:to_i)
45
+
46
+ hour >= 24 ? parse_midnight_time(date, hour, minute) : Time.parse(datetime)
54
47
  end
55
48
 
56
- def get_region_code(region_name)
57
- region_list = get_region_list
58
- region_list[region_name.to_sym]
49
+ def parse_midnight_time(date_str, hour, minute)
50
+ day_add = hour / 24
51
+ hour %= 24
52
+
53
+ datetime = Time.parse(date_str)
54
+ datetime += day_add * 60 * 60 * 24
55
+ datetime += hour * 60 * 60
56
+ datetime += minute * 60
57
+
58
+ datetime
59
59
  end
60
60
  end
61
+
62
+ class ParseError < StandardError; end
61
63
  end
@@ -0,0 +1,58 @@
1
+ module Nowtv
2
+ class Region
3
+ @prefectures = %w{
4
+ hokkaido
5
+ aomori
6
+ iwate
7
+ miyagi
8
+ akita
9
+ yamagata
10
+ fukushima
11
+ ibaraki
12
+ tochigi
13
+ gunma
14
+ saitama
15
+ chiba
16
+ tokyo
17
+ kanagawa
18
+ niigata
19
+ toyama
20
+ ishikawa
21
+ fukui
22
+ yamanashi
23
+ nagano
24
+ figu
25
+ shizuoka
26
+ aichi
27
+ mie
28
+ shiga
29
+ kyoto
30
+ osaka
31
+ hyogo
32
+ nara
33
+ wakayama
34
+ tottori
35
+ shimane
36
+ okayama
37
+ hiroshima
38
+ yamaguchi
39
+ tokushima
40
+ kagawa
41
+ ehime
42
+ kochi
43
+ fukuoka
44
+ saga
45
+ nagasaki
46
+ kumamoto
47
+ oita
48
+ miyazaki
49
+ kagoshima
50
+ okinawa
51
+ }
52
+
53
+ def self.get_region_id(prefecture)
54
+ prefecture = prefecture.downcase
55
+ @prefectures.include?(prefecture) ? @prefectures.index(prefecture) + 1 : 0
56
+ end
57
+ end
58
+ end
@@ -1,3 +1,3 @@
1
1
  module Nowtv
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "guard-rspec"
25
25
  spec.add_development_dependency "webmock"
26
26
  spec.add_development_dependency "simplecov"
27
+ spec.add_development_dependency "coveralls"
27
28
  end
@@ -1,89 +1,62 @@
1
1
  # -*- coding: utf-8 -*-
2
- EXAMPLE_VALID_PROGRAMS_BODY = <<-EOS
3
- ({"error":0,"ccode":null,"region_code":"tokyo","media":{"code":"02","name":"\u5730\u4e0a\u6ce2"},"region":{"code":"tokyo","name":"\u6771\u4eac"},"programs":[{"station_code":"02-*01","station_name":"NHK\u7dcf\u5408","start":"201309131930","end":"201309131955","title":"\u7279\u5831\u9996\u90fd\u570f"},{"station_code":"02-#01","station_name":"NHK E\u30c6\u30ec","start":"201309131925","end":"201309131948","title":"\u8ab2\u5916\u6388\u696d\u3000\u3088\u3046\u3053\u305d\u5148\u8f29\u30fb\u9078"},{"station_code":"02-NTV","station_name":"\u65e5\u672c\u30c6\u30ec\u30d3","start":"201309131900","end":"201309132054","title":"\u7dca\u6025\u51fa\u52d5\uff01\u9003\u8d70\u8eca\u3092\u8ffd\u3048\uff01\u4ea4\u901a\u8b66\u5bdf\u3000\u771f\u590f\u306e\u5927\u635c\u67fb\u7dda"},{"station_code":"02-EX ","station_name":"\u30c6\u30ec\u30d3\u671d\u65e5","start":"201309131900","end":"201309131954","title":"\u30c9\u30e9\u3048\u3082\u3093\u8a95\u751f\u65e5\uff11\u6642\u9593\u30b9\u30da\u30b7\u30e3\u30eb"},{"station_code":"02-TBS","station_name":"TBS\u30c6\u30ec\u30d3","start":"201309131900","end":"201309131956","title":"\u7206\u5831\uff01\uff34\uff28\uff25\u3000\u30d5\u30e9\u30a4\u30c7\u30fc"},{"station_code":"02-TX ","station_name":"\u30c6\u30ec\u30d3\u6771\u4eac","start":"201309131830","end":"201309131950","title":"\u304a\u91d1\u304c\u306a\u304f\u3066\u3082\u5e78\u305b\u30e9\u30a4\u30d5\u3000\u304c\u3093\u3070\u308c\u30d7\u30a2\u30fc\u30ba\uff01"},{"station_code":"02-CX","station_name":"\u30d5\u30b8\u30c6\u30ec\u30d3","start":"201309131900","end":"201309131957","title":"\u30da\u30b1\u30dd\u30f3"},{"station_code":"02-MX ","station_name":"TOKYO MX","start":"201309131930","end":"201309132000","title":"\u3081\u305e\u3093\u4e00\u523b"},{"station_code":"02-HDT","station_name":"\u653e\u9001\u5927\u5b66\u30c6\u30ec\u30d3","start":"201309131900","end":"201309131945","title":"\u6587\u5316\u4eba\u985e\u5b66\u7b2c\uff11\uff11\u56de"}]})
4
- EOS
2
+ require "time"
5
3
 
6
- EXAMPLE_INVALID_PROGRAMS_BODY = <<-EOS
7
- ({"error":0,"ccode":null,"region_code":"aaa","media":{"code":"02","name":"\u5730\u4e0a\u6ce2"},"region":{"code":null,"name":null},"programs":[]})
4
+ VALID_PROGRAMS_BODY = <<-EOS
5
+ {"SystemInfomation":{"id":0},"ProgramScheduleInfomartion":{"mediaId":"1","PackId":"107","stationnumber":8,"Name":{"packName":"\u6771\u4eac","packUrl":""},"MediaLocation":{"StationLocation":[{"stationCode":"Z0031","stationUrl":"http:\/\/www.nhk.or.jp\/","additionalDisplayChannel":"\u5730\u4e0a\u30c7\u30b8\u30bf\u30eb\uff081\uff09","stationDispName":"NHK\u7dcf\u5408","channel":"","channelId":"4228","programnumber":1,"ProgramInformation":{"startDateTime":"2014\/04\/19 21:00","endDateTime":"2014\/04\/19 22:00","programId":"731","programcode":"tokyoZ00310000004228201404192100","officialurl":"","modecode":"100000000110000010000000010000000000000000000000000000000000000000000000","programTitle":"\u30ed\u30f3\u30b0\u30fb\u30b0\u30c3\u30c9\u30d0\u30a4","programSubTitle":"\u300c\u8272\u7537\u6b7b\u3059\u300d","programContent":"\u30df\u30b9\u30c6\u30ea\u30fc\u306e\u91d1\u5b57\u5854\u521d\u30c9\u30e9\u30de\u5316\u3000\u6d45\u91ce\u5fe0\u4fe1\u3000\u7dbe\u91ce\u525b\u3000\u5c0f\u96ea\u3000\u53e4\u7530\u65b0\u592a\u3000\u51a8\u6c38\u611b\u3000\u592a\u7530\u8389\u83dc\u3000\u7530\u53e3\u30c8\u30e2\u30ed\u30f2\u3000\u6edd\u85e4\u8ce2\u4e00\u3000\u9060\u85e4\u61b2\u4e00\u3000\u67c4\u672c\u660e","Genre":{"genreId":"2","color":"ffffcc"},"programExplanation":"\u3000\uff11\uff19\uff15\uff10\u5e74\u4ee3\u534a\u3070\u306e\u6771\u4eac\u3002\u6226\u5f8c\u5fa9\u8208\u304b\u3089\u306e\u5927\u8ee2\u63db\u671f\u306b\u3001\u4eba\u3005\u306e\u4fa1\u5024\u89b3\u304c\u5927\u304d\u304f\u5909\u5316\u3057\u3066\u3044\u304f\u6fc0\u6d41\u306e\u4e2d\u3067\u3001\u771f\u306b\u6b63\u3057\u3044\u9053\u3060\u3051\u3092\u9078\u3073\u751f\u304d\u3066\u3044\u304f\u79c1\u7acb\u63a2\u5075\u30fb\u5897\u6ca2\u78d0\u4e8c(\u6d45\u91ce\u5fe0\u4fe1)\u306e\u59ff\u3092\u63cf\u304f\u30df\u30b9\u30c6\u30ea\u30fc\u3002\u539f\u4f5c\u30ec\u30a4\u30e2\u30f3\u30c9\u30fb\u30c1\u30e3\u30f3\u30c9\u30e9\u30fc\u3001\u811a\u672c\u30fb\u6e21\u8fba\u3042\u3084\u3001\u6f14\u51fa\u30fb\u5800\u5207\u5712\u5065\u592a\u90ce\u3002\u3000\u79c1\u7acb\u63a2\u5075\u30fb\u78d0\u4e8c(\u6d45\u91ce)\u306f\u3001\u9154\u3063\u3071\u3089\u3063\u3066\u5012\u308c\u3066\u3044\u305f\u4fdd(\u7dbe\u91ce\u525b)\u3092\u52a9\u3051\u3066\u4ee5\u6765\u3001\u30d0\u30fc\u3067\u9152\u3092\u914c\u307f\u4ea4\u308f\u3059\u4ef2\u306b\u306a\u308b\u3002\u3042\u308b\u591c\u3001\u30d4\u30b9\u30c8\u30eb\u3092\u624b\u306b\u3057\u305f\u4fdd\u304c\u3001\u78d0\u4e8c\u306e\u4e8b\u52d9\u6240\u306b\u73fe\u308c\u305f\u3002\u8a00\u308f\u308c\u308b\u307e\u307e\u306b\u53f0\u6e7e\u884c\u304d\u306e\u8239\u304c\u51fa\u308b\u6e2f\u307e\u3067\u4fdd\u3092\u9001\u3063\u305f\u78d0\u4e8c\u306f\u3001\u7fcc\u65e5\u3001\u8b66\u5bdf\u306b\u9023\u884c\u3055\u308c\u308b\u3002\u59bb\u6bba\u5bb3\u306e\u5bb9\u7591\u306e\u639b\u304b\u3063\u305f\u4fdd\u306e\u9003\u4ea1\u3092\u624b\u52a9\u3051\u3057\u305f\u3068\u7591\u308f\u308c\u305f\u306e\u3060\u3002","gcode":""}},{"stationCode":"Z0051","stationUrl":"http:\/\/www.nhk.or.jp\/e-tele\/","additionalDisplayChannel":"\u5730\u4e0a\u30c7\u30b8\u30bf\u30eb\uff082\uff09","stationDispName":"NHK E\u30c6\u30ec","channel":"","channelId":"4229","programnumber":1,"ProgramInformation":{"startDateTime":"2014\/04\/19 21:30","endDateTime":"2014\/04\/19 22:00","programId":"815","programcode":"tokyoZ00510000004229201404192130","officialurl":"","modecode":"100000000100000010000000000000000000000000000000000000000000000000000000","programTitle":"\u3089\u3089\u3089\u3000\u30af\u30e9\u30b7\u30c3\u30af","programSubTitle":"\u300c\u68ee\u3068\u6e56\u3068\u97f3\u697d\u3068\uff5e\u30b7\u30d9\u30ea\u30a6\u30b9\u306e\u201c\u30d5\u30a3\u30f3\u30e9\u30f3\u30c7\u30a3\u30a2\u201d\uff5e\u300d","programContent":"\u5317\u6b27\u30b7\u30d9\u30ea\u30a6\u30b9\u306e\u540d\u66f2\u201c\u30d5\u30a3\u30f3\u30e9\u30f3\u30c7\u30a3\u30a2\u201d","Genre":{"genreId":"5","color":"ccffcc"},"programExplanation":"","gcode":""}},{"stationCode":"Z0084","stationUrl":"http:\/\/www.ntv.co.jp\/","additionalDisplayChannel":"\u5730\u4e0a\u30c7\u30b8\u30bf\u30eb\uff084\uff09","stationDispName":"\u65e5\u672c\u30c6\u30ec\u30d3","channel":"","channelId":"4230","programnumber":1,"ProgramInformation":{"startDateTime":"2014\/04\/19 21:54","endDateTime":"2014\/04\/19 26:00","programId":"856","programcode":"tokyoZ00840000004230201404192154","officialurl":"","modecode":"100000000100000000000000000000000000000000000000000000000000000000000000","programTitle":"\u30b3\u30eb\u30af\u3092\u629c\u304f\u77ac\u9593","programSubTitle":"","programContent":"","Genre":{"genreId":"8","color":null},"programExplanation":"","gcode":""}},{"stationCode":"Z0085","stationUrl":"http:\/\/www.tbs.co.jp\/","additionalDisplayChannel":"\u5730\u4e0a\u30c7\u30b8\u30bf\u30eb\uff086\uff09","stationDispName":"TBS\u30c6\u30ec\u30d3","channel":"","channelId":"4231","programnumber":1,"ProgramInformation":{"startDateTime":"2014\/04\/19 21:54","endDateTime":"2014\/04\/19 22:00","programId":"897","programcode":"tokyoZ00850000004231201404192154","officialurl":"","modecode":"100000000100000010000000000000000000000000000000000000000000000000000000","programTitle":"\u30b9\u30c3\u30d4\u30f3\uff3a","programSubTitle":"","programContent":"","Genre":{"genreId":"6","color":null},"programExplanation":"","gcode":""}},{"stationCode":"Z0086","stationUrl":"http:\/\/www.fujitv.co.jp\/","additionalDisplayChannel":"\u5730\u4e0a\u30c7\u30b8\u30bf\u30eb\uff088\uff09","stationDispName":"\u30d5\u30b8\u30c6\u30ec\u30d3","channel":"","channelId":"4232","programnumber":1,"ProgramInformation":{"startDateTime":"2014\/04\/19 21:00","endDateTime":"2014\/04\/19 23:10","programId":"938","programcode":"tokyoZ00860000004232201404192100","officialurl":"","modecode":"100000000100000010000000000000000000000000000000000000000000000000000000","programTitle":"\u3055\u3093\u307e\uff06\u304f\u308a\u3043\u3080\u306e\u7b2c\uff11\uff17\u56de\u82b8\u80fd\u754c(\u79d8)\u500b\u4eba\u60c5\u5831\u30b0\u30e9\u30f3\u30d7\u30ea","programSubTitle":"","programContent":"\u8d85\u8c6a\u83ef\u82b8\u80fd\u4eba\uff13\uff15\u4eba\u96c6\u7d50(\u79d8)\u8d64\u9762\u904e\u53bb\u6620\u50cf\u5927\u6d41\u51fa\u4eba\u6c17\u5973\u5b50\u30a2\u30ca\u65b0\u4eba\u6642\u4ee3\u77e5\u3089\u308c\u3056\u308b\u82b8\u80fd\u4eba\u5bb6\u65cf\uff13\u5104\u7a3c\u3050\u6b66\u4e95\u58ee\u3044\u3068\u3053\uff2d\u306e\u5148\u7956\u306f\u6c34\u6238\u9ec4\u9580\uff01\uff01\u738b\u8005\u8179\u82b8\uff36\uff33\u86ed\u5b50\u30e9\u30c3\u30d7\uff36\uff33\u4e94\u6708\u30c0\u30f3\u30b9(\u79d8)\u73cd\u7279\u6280\u3000\u660e\u77f3\u5bb6\u3055\u3093\u307e\u3000\u304f\u308a\u3043\u3080\u3057\u3061\u3085\u30fc\u3000\u52a0\u85e4\u7dbe\u5b50\u3000\u30a2\u30cb\u30de\u30eb\u6d5c\u53e3\u3000\u30a6\u30fc\u30de\u30f3\u30e9\u30c3\u30b7\u30e5\u30a2\u30ef\u30fc\u3000\u86ed\u5b50\u80fd\u53ce\u3000\u5ddd\u5408\u4fca\u4e00\u3000\uff2a\uff2f\uff39\u3000\u6b66\u4e95\u58ee\u3000\u30c7\u30cb\u30b9","Genre":{"genreId":"6","color":null},"programExplanation":"","gcode":""}},{"stationCode":"Z0087","stationUrl":"http:\/\/www.tv-asahi.co.jp\/","additionalDisplayChannel":"\u5730\u4e0a\u30c7\u30b8\u30bf\u30eb\uff085\uff09","stationDispName":"\u30c6\u30ec\u30d3\u671d\u65e5","channel":"","channelId":"4233","programnumber":1,"ProgramInformation":{"startDateTime":"2014\/04\/19 21:00","endDateTime":"2014\/04\/19 23:06","programId":"981","programcode":"tokyoZ00870000004233201404192100","officialurl":"","modecode":"100000000110000010000000000000000000000000001000000000000000000000000000","programTitle":"\u9006\u8ee2\u5831\u9053\u306e\u5973(\uff13)","programSubTitle":"\u300c\u30ef\u30b1\u3042\u308a\u4e3b\u5a66\u30ad\u30e3\u30b9\u30bf\u30fc\u304c\u6311\u3080\u706b\u30c0\u30eb\u30de\u9023\u7d9a\u6bba\u4eba\u5c01\u5370\u3055\u308c\u305f\u76ee\u6483\u8a3c\u8a00\uff01\u88ab\u5bb3\u8005\u3092\u7d50\u3076\uff15\u5e74\u524d\u306e\u51a4\u7f6a\u4e8b\u4ef6\uff01\uff1f\u5fa9\u8b90\u306e\u708e\u304c\u3042\u3076\u308a\u51fa\u3059\u8b0e\u306e\u8a18\u61b6\u300d","programContent":"\u3000\u9ad8\u5cf6\u793c\u5b50\u3000\u539f\u7530\u9f8d\u4e8c\u3000\u6c34\u91ce\u4e45\u7f8e\u3000\u4e2d\u539f\u4e08\u96c4\u3000\u76ca\u5ca1\u5fb9\u3000\u8fd1\u6c5f\u8c37\u592a\u6717\u3000\u79cb\u672c\u7950\u5e0c\u3000\u671d\u5009\u4f38\u4e8c\u3000\u82e5\u8449\u7adc\u4e5f\u3000\u6e21\u8fba\u54f2","Genre":{"genreId":"2","color":"ffffcc"},"programExplanation":"","gcode":""}},{"stationCode":"Z0088","stationUrl":"http:\/\/www.tv-tokyo.co.jp\/","additionalDisplayChannel":"\u5730\u4e0a\u30c7\u30b8\u30bf\u30eb\uff087\uff09","stationDispName":"\u30c6\u30ec\u30d3\u6771\u4eac","channel":"","channelId":"4234","programnumber":1,"ProgramInformation":{"startDateTime":"2014\/04\/19 21:54","endDateTime":"2014\/04\/19 22:00","programId":"1037","programcode":"tokyoZ00880000004234201404192154","officialurl":"http:\/\/www.tv-tokyo.co.jp\/manbo\/","modecode":"100000000100000010000000000000000000000000000000000000000000000000000000","programTitle":"\u3074\u304b\u3074\u304b\u30de\u30f3\u30dc","programSubTitle":"","programContent":"\u7c21\u5358\u5bb6\u4e8b\u8853","Genre":{"genreId":"8","color":null},"programExplanation":"","gcode":""}},{"stationCode":"Z0016","stationUrl":"http:\/\/www.mxtv.co.jp\/","additionalDisplayChannel":"\u5730\u4e0a\u30c7\u30b8\u30bf\u30eb\uff089\uff09","stationDispName":"TOKYO MX","channel":"","channelId":"4235","programnumber":1,"ProgramInformation":{"startDateTime":"2014\/04\/19 21:58","endDateTime":"2014\/04\/19 22:00","programId":"669","programcode":"tokyoZ00160000004235201404192158","officialurl":"","modecode":"100000000100000000000000000000000000000000000000000000000000000000000000","programTitle":"\uff34\uff2f\uff2b\uff39\uff2f\u3000\uff2d\uff38\u3000\uff2e\uff25\uff37\uff33","programSubTitle":"","programContent":"\u3000\u9e7f\u5185\u7f8e\u6c99","Genre":{"genreId":"9","color":null},"programExplanation":"","gcode":""}}]}}}
8
6
  EOS
9
7
 
10
- EXAMPLE_PROGRAMS =
11
- [
12
- {"station_code"=>"02-*01", "station_name"=>"NHK総合", "start"=>"201309131930", "end"=>"201309131955", "title"=>"特報首都圏"},
13
- {"station_code"=>"02-#01", "station_name"=>"NHK Eテレ", "start"=>"201309131925", "end"=>"201309131948", "title"=>"課外授業 ようこそ先輩・選"},
14
- {"station_code"=>"02-NTV", "station_name"=>"日本テレビ", "start"=>"201309131900", "end"=>"201309132054", "title"=>"緊急出動!逃走車を追え!交通警察 真夏の大捜査線"},
15
- {"station_code"=>"02-EX ", "station_name"=>"テレビ朝日", "start"=>"201309131900", "end"=>"201309131954", "title"=>"ドラえもん誕生日1時間スペシャル"},
16
- {"station_code"=>"02-TBS", "station_name"=>"TBSテレビ", "start"=>"201309131900", "end"=>"201309131956", "title"=>"爆報!THE フライデー"},
17
- {"station_code"=>"02-TX ", "station_name"=>"テレビ東京", "start"=>"201309131830", "end"=>"201309131950", "title"=>"お金がなくても幸せライフ がんばれプアーズ!"},
18
- {"station_code"=>"02-CX", "station_name"=>"フジテレビ", "start"=>"201309131900", "end"=>"201309131957", "title"=>"ペケポン"},
19
- {"station_code"=>"02-MX ", "station_name"=>"TOKYO MX", "start"=>"201309131930", "end"=>"201309132000", "title"=>"めぞん一刻"},
20
- {"station_code"=>"02-HDT", "station_name"=>"放送大学テレビ", "start"=>"201309131900", "end"=>"201309131945", "title"=>"文化人類学第11回"}
21
- ]
8
+ INVALID_PROGRAMS_BODY = <<-EOS
9
+ {"SystemInfomation":{"id":0},"ProgramScheduleInfomartion":null}
10
+ EOS
22
11
 
23
- EXAMPLE_RESTRUCTED_PROGRAMS =
12
+ PROGRAM_LIST =
24
13
  [
25
- {station: "NHK総合", title: "特報首都圏", start_time: "19:30", end_time: "19:55"},
26
- {station: "NHK Eテレ", title: "課外授業 ようこそ先輩・選", start_time: "19:25", end_time: "19:48"},
27
- {station: "日本テレビ", title: "緊急出動!逃走車を追え!交通警察 真夏の大捜査線", start_time: "19:00", end_time: "20:54"},
28
- {station: "テレビ朝日", title: "ドラえもん誕生日1時間スペシャル", start_time: "19:00", end_time: "19:54"},
29
- {station: "TBSテレビ", title: "爆報!THE フライデー", start_time: "19:00", end_time: "19:56"},
30
- {station: "テレビ東京", title: "お金がなくても幸せライフ がんばれプアーズ!", start_time: "18:30", end_time: "19:50"},
31
- {station: "フジテレビ", title: "ペケポン", start_time: "19:00", end_time: "19:57"},
32
- {station: "TOKYO MX", title: "めぞん一刻", start_time: "19:30", end_time: "20:00"},
33
- {station: "放送大学テレビ", title: "文化人類学第11回", start_time: "19:00", end_time: "19:45"}
14
+ {
15
+ station: "NHK総合",
16
+ title: "ロング・グッドバイ",
17
+ start_time: Time.parse("2014/04/19 21:00"),
18
+ end_time: Time.parse("2014/04/19 22:00")
19
+ },
20
+ {
21
+ station: "NHK Eテレ",
22
+ title: "ららら クラシック",
23
+ start_time: Time.parse("2014/04/19 21:30"),
24
+ end_time: Time.parse("2014/04/19 22:00")
25
+ },
26
+ {
27
+ station: "日本テレビ",
28
+ title: "コルクを抜く瞬間",
29
+ start_time: Time.parse("2014/04/19 21:54"),
30
+ end_time: Time.parse("2014/04/20 02:00")
31
+ },
32
+ {
33
+ station: "TBSテレビ",
34
+ title: "スッピンZ",
35
+ start_time: Time.parse("2014/04/19 21:54"),
36
+ end_time: Time.parse("2014/04/19 22:00")
37
+ },
38
+ {
39
+ station: "フジテレビ",
40
+ title: "さんま&くりぃむの第17回芸能界(秘)個人情報グランプリ",
41
+ start_time: Time.parse("2014/04/19 21:00"),
42
+ end_time: Time.parse("2014/04/19 23:10")
43
+ },
44
+ {
45
+ station: "テレビ朝日",
46
+ title: "逆転報道の女(3)",
47
+ start_time: Time.parse("2014/04/19 21:00"),
48
+ end_time: Time.parse("2014/04/19 23:06")
49
+ },
50
+ {
51
+ station: "テレビ東京",
52
+ title: "ぴかぴかマンボ",
53
+ start_time: Time.parse("2014/04/19 21:54"),
54
+ end_time: Time.parse("2014/04/19 22:00")
55
+ },
56
+ {
57
+ station: "TOKYO MX",
58
+ title: "TOKYO MX NEWS",
59
+ start_time: Time.parse("2014/04/19 21:58"),
60
+ end_time: Time.parse("2014/04/19 22:00")
61
+ }
34
62
  ]
35
-
36
- EXAMPLE_REGION_BODY = <<-EOS
37
- ({"error":0,"ccode":null,"media_code":null,"regions":[{"code":"hokk","name":"\u5317\u6d77\u9053","pack_code":null},{"code":"aomori","name":"\u9752\u68ee","pack_code":null},{"code":"iwate","name":"\u5ca9\u624b","pack_code":null},{"code":"miya","name":"\u5bae\u57ce","pack_code":null},{"code":"akita","name":"\u79cb\u7530","pack_code":null},{"code":"yamagata","name":"\u5c71\u5f62","pack_code":null},{"code":"fuku","name":"\u798f\u5cf6","pack_code":null},{"code":"ibaraki","name":"\u8328\u57ce","pack_code":null},{"code":"tochigi","name":"\u6803\u6728","pack_code":null},{"code":"gunma","name":"\u7fa4\u99ac","pack_code":null},{"code":"saitama","name":"\u57fc\u7389","pack_code":null},{"code":"chiba","name":"\u5343\u8449","pack_code":null},{"code":"tokyo","name":"\u6771\u4eac","pack_code":null},{"code":"kanagawa","name":"\u795e\u5948\u5ddd","pack_code":null},{"code":"niigata","name":"\u65b0\u6f5f","pack_code":null},{"code":"toyama","name":"\u5bcc\u5c71","pack_code":null},{"code":"ishikawa","name":"\u77f3\u5ddd","pack_code":null},{"code":"fukui","name":"\u798f\u4e95","pack_code":null},{"code":"yamanasi","name":"\u5c71\u68a8","pack_code":null},{"code":"nagano","name":"\u9577\u91ce","pack_code":null},{"code":"gifu","name":"\u5c90\u961c","pack_code":null},{"code":"sizu","name":"\u9759\u5ca1","pack_code":null},{"code":"aichi","name":"\u611b\u77e5","pack_code":null},{"code":"mie","name":"\u4e09\u91cd","pack_code":null},{"code":"siga","name":"\u6ecb\u8cc0","pack_code":null},{"code":"kyoto","name":"\u4eac\u90fd","pack_code":null},{"code":"osaka","name":"\u5927\u962a","pack_code":null},{"code":"hyougo","name":"\u5175\u5eab","pack_code":null},{"code":"nara","name":"\u5948\u826f","pack_code":null},{"code":"wakayama","name":"\u548c\u6b4c\u5c71","pack_code":null},{"code":"tottori","name":"\u9ce5\u53d6","pack_code":null},{"code":"shimane","name":"\u5cf6\u6839","pack_code":null},{"code":"okayama","name":"\u5ca1\u5c71","pack_code":null},{"code":"hirosima","name":"\u5e83\u5cf6","pack_code":null},{"code":"yamagchi","name":"\u5c71\u53e3","pack_code":null},{"code":"tokusima","name":"\u5fb3\u5cf6","pack_code":null},{"code":"kagawa","name":"\u9999\u5ddd","pack_code":null},{"code":"ehime","name":"\u611b\u5a9b","pack_code":null},{"code":"kouchi","name":"\u9ad8\u77e5","pack_code":null},{"code":"fukuoka","name":"\u798f\u5ca1","pack_code":null},{"code":"saga","name":"\u4f50\u8cc0","pack_code":null},{"code":"nagasaki","name":"\u9577\u5d0e","pack_code":null},{"code":"kumamoto","name":"\u718a\u672c","pack_code":null},{"code":"oita","name":"\u5927\u5206","pack_code":null},{"code":"miyazaki","name":"\u5bae\u5d0e","pack_code":null},{"code":"kagosima","name":"\u9e7f\u5150\u5cf6","pack_code":null},{"code":"nawa","name":"\u6c96\u7e04","pack_code":null}]})
38
- EOS
39
-
40
- EXAMPLE_REGION_LIST =
41
- {
42
- 北海道: "hokk",
43
- 青森: "aomori",
44
- 岩手: "iwate",
45
- 宮城: "miya",
46
- 秋田: "akita",
47
- 山形: "yamagata",
48
- 福島: "fuku",
49
- 茨城: "ibaraki",
50
- 栃木: "tochigi",
51
- 群馬: "gunma",
52
- 埼玉: "saitama",
53
- 千葉: "chiba",
54
- 東京: "tokyo",
55
- 神奈川: "kanagawa",
56
- 新潟: "niigata",
57
- 富山: "toyama",
58
- 石川: "ishikawa",
59
- 福井: "fukui",
60
- 山梨: "yamanasi",
61
- 長野: "nagano",
62
- 岐阜: "gifu",
63
- 静岡: "sizu",
64
- 愛知: "aichi",
65
- 三重: "mie",
66
- 滋賀: "siga",
67
- 京都: "kyoto",
68
- 大阪: "osaka",
69
- 兵庫: "hyougo",
70
- 奈良: "nara",
71
- 和歌山: "wakayama",
72
- 鳥取: "tottori",
73
- 島根: "shimane",
74
- 岡山: "okayama",
75
- 広島: "hirosima",
76
- 山口: "yamagchi",
77
- 徳島: "tokusima",
78
- 香川: "kagawa",
79
- 愛媛: "ehime",
80
- 高知: "kouchi",
81
- 福岡: "fukuoka",
82
- 佐賀: "saga",
83
- 長崎: "nagasaki",
84
- 熊本: "kumamoto",
85
- 大分: "oita",
86
- 宮崎: "miyazaki",
87
- 鹿児島: "kagosima",
88
- 沖縄: "nawa"
89
- }
@@ -4,94 +4,43 @@ require 'webmock/rspec'
4
4
 
5
5
  WebMock.allow_net_connect!
6
6
 
7
- API_URL = 'http://asp.tvguide.or.jp/api/broadcasting?region_code='
8
- REGION_URL = 'http://asp.tvguide.or.jp/api/regions'
7
+ API_URL = 'http://www.tvguide.or.jp/TXML301PG.php?type=TVG&regionId='
9
8
 
10
9
  module Nowtv
11
10
  describe Client do
12
- before(:all) do
13
- load File.expand_path("../../fixtures/fixtures.rb", __dir__)
14
- @client = Nowtv::Client.new
15
- @valid_region_code = 'tokyo'
16
- @valid_region_name = '東京'
17
- @invalid_region_code = 'nihon'
18
- @invalid_region_name = '日本'
19
- end
20
-
21
- before do
22
- stub_request(:get, API_URL + @valid_region_code)
23
- .to_return(body: EXAMPLE_VALID_PROGRAMS_BODY, status: 200)
24
- stub_request(:get, API_URL + @invalid_region_code)
25
- .to_return(body: EXAMPLE_INVALID_PROGRAMS_BODY, status: 200)
26
- stub_request(:get, REGION_URL).to_return(body: EXAMPLE_REGION_BODY, status: 200)
27
- end
11
+ load File.expand_path("../../fixtures/fixtures.rb", File.dirname(__FILE__))
28
12
 
29
- describe '#get_programs' do
30
- context 'with valid region code' do
31
- subject { @client.get_programs(@valid_region_code) }
32
- it { should be_instance_of Array }
33
- it { should have_at_least(1).items }
34
- end
13
+ let(:client) { Nowtv::Client.new }
14
+ let(:valid_region_code) { 13 }
15
+ let(:invalid_region_code) { "tokyo" }
35
16
 
36
- context 'with invalid region' do
37
- subject { @client.get_programs(@invalid_region_code) }
38
- it { should be_instance_of Array }
39
- it { should have(0).items }
40
- end
17
+ before do
18
+ stub_request(:get, API_URL + valid_region_code.to_s)
19
+ .to_return(body: VALID_PROGRAMS_BODY, status: 200)
20
+ stub_request(:get, API_URL + invalid_region_code.to_s)
21
+ .to_return(body: INVALID_PROGRAMS_BODY, status: 200)
41
22
  end
42
23
 
43
24
  describe '#get_program_list' do
44
25
  context 'with valid region code' do
45
- subject { @client.get_program_list(@valid_region_code) }
46
- it { should be_instance_of Array }
47
- it 'should be equal to example data' do
48
- should eql EXAMPLE_RESTRUCTED_PROGRAMS
26
+ let(:program_list) { client.get_program_list(valid_region_code) }
27
+
28
+ it "should be Array" do
29
+ expect(program_list).to be_a Array
49
30
  end
50
- end
51
31
 
52
- context 'with valid region name' do
53
- subject { @client.get_program_list(@valid_region_name) }
54
- it { should be_instance_of Array }
55
- it 'should be equal to example data' do
56
- should eql EXAMPLE_RESTRUCTED_PROGRAMS
32
+ it "should be return program list" do
33
+ expect(program_list).to be_eql PROGRAM_LIST
57
34
  end
58
35
  end
59
36
 
60
37
  context 'with invalid region code' do
61
38
  it 'should put error message in STDERR' do
62
- $stderr.should_receive(:puts).with('Failed to get programs!')
63
- @program_list = @client.get_program_list(@invalid_region_code)
39
+ expect do
40
+ client.get_program_list(invalid_region_code)
41
+ end.to raise_error ParseError, "Failed to parse program data"
64
42
  end
65
43
  end
66
44
  end
67
-
68
- describe '#restrct_program_list' do
69
- subject { @client.restruct_program_list(EXAMPLE_PROGRAMS) }
70
- it { should be_instance_of Array }
71
- it 'should be equal to example data' do
72
- should eql EXAMPLE_RESTRUCTED_PROGRAMS
73
- end
74
- end
75
-
76
- describe '#get_region_list' do
77
- subject { @client.get_region_list }
78
- it { should be_instance_of Hash }
79
- it { should have(47).items }
80
- it 'should be equal to example data' do
81
- should eq EXAMPLE_REGION_LIST
82
- end
83
- end
84
-
85
- describe '#get_region_code' do
86
- context 'with valid name' do
87
- subject { @client.get_region_code(@valid_region_name) }
88
- it { should == @valid_region_code }
89
- end
90
-
91
- context 'with invalid name' do
92
- subject { @client.get_region_code(@invalid_region_name) }
93
- it { should be_nil }
94
- end
95
- end
96
45
  end
97
46
  end
@@ -0,0 +1,25 @@
1
+ require "spec_helper"
2
+
3
+ module Nowtv
4
+ describe Region do
5
+ describe "#get_region_id" do
6
+ context "with valid prefecture name" do
7
+ it "should return region id" do
8
+ expect(Nowtv::Region.get_region_id("tokyo")).to eq 13
9
+ end
10
+ end
11
+
12
+ context "with valid capitalized prefecture name" do
13
+ it "should return region id" do
14
+ expect(Nowtv::Region.get_region_id("TOKYO")).to eq 13
15
+ end
16
+ end
17
+
18
+ context "with invalid prefecture name" do
19
+ it "should return 0" do
20
+ expect(Nowtv::Region.get_region_id("nippon")).to eq 0
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,4 +1,7 @@
1
1
  require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
2
5
  SimpleCov.start
3
6
 
4
7
  # This file was generated by the `rspec --init` command. Conventionally, all
metadata CHANGED
@@ -1,97 +1,111 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nowtv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - dtan4
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-06 00:00:00.000000000 Z
11
+ date: 2014-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: guard-rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: webmock
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: simplecov
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: coveralls
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
111
  description: Show current TV programs
@@ -102,10 +116,10 @@ executables:
102
116
  extensions: []
103
117
  extra_rdoc_files: []
104
118
  files:
105
- - .gitignore
106
- - .nowtv
107
- - .rspec
108
- - .travis.yml
119
+ - ".gitignore"
120
+ - ".nowtv"
121
+ - ".rspec"
122
+ - ".travis.yml"
109
123
  - Gemfile
110
124
  - Guardfile
111
125
  - LICENSE.txt
@@ -114,10 +128,12 @@ files:
114
128
  - bin/nowtv
115
129
  - lib/nowtv.rb
116
130
  - lib/nowtv/client.rb
131
+ - lib/nowtv/region.rb
117
132
  - lib/nowtv/version.rb
118
133
  - nowtv.gemspec
119
134
  - spec/fixtures/fixtures.rb
120
135
  - spec/lib/nowtv/client_spec.rb
136
+ - spec/lib/nowtv/region_spec.rb
121
137
  - spec/spec_helper.rb
122
138
  homepage: https://github.com/dtan4/nowtv
123
139
  licenses:
@@ -129,21 +145,22 @@ require_paths:
129
145
  - lib
130
146
  required_ruby_version: !ruby/object:Gem::Requirement
131
147
  requirements:
132
- - - '>='
148
+ - - ">="
133
149
  - !ruby/object:Gem::Version
134
150
  version: '0'
135
151
  required_rubygems_version: !ruby/object:Gem::Requirement
136
152
  requirements:
137
- - - '>='
153
+ - - ">="
138
154
  - !ruby/object:Gem::Version
139
155
  version: '0'
140
156
  requirements: []
141
157
  rubyforge_project:
142
- rubygems_version: 2.1.0
158
+ rubygems_version: 2.2.2
143
159
  signing_key:
144
160
  specification_version: 4
145
161
  summary: Show current TV programs
146
162
  test_files:
147
163
  - spec/fixtures/fixtures.rb
148
164
  - spec/lib/nowtv/client_spec.rb
165
+ - spec/lib/nowtv/region_spec.rb
149
166
  - spec/spec_helper.rb