weatherhacks 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/License.txt +56 -0
- data/Manifest.txt +30 -0
- data/README.txt +9 -0
- data/Rakefile +4 -0
- data/bin/lwws +58 -0
- data/config/hoe.rb +71 -0
- data/config/requirements.rb +17 -0
- data/lib/weatherhacks/forecastmap.rb +266 -0
- data/lib/weatherhacks/lwws.rb +140 -0
- data/lib/weatherhacks/version.rb +9 -0
- data/lib/weatherhacks.rb +58 -0
- data/misc/forecastmap.xsl +45 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/spec/lwws_spec.rb +243 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +11 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/weatherhacks.rake +20 -0
- data/tasks/website.rake +17 -0
- data/website/index.html +119 -0
- data/website/index.txt +57 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.rhtml +48 -0
- metadata +80 -0
data/History.txt
ADDED
data/License.txt
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
|
2
|
+
You can redistribute it and/or modify it under either the terms of the GPL
|
3
|
+
(see the file GPL), or the conditions below:
|
4
|
+
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
6
|
+
software without restriction, provided that you duplicate all of the
|
7
|
+
original copyright notices and associated disclaimers.
|
8
|
+
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
10
|
+
you do at least ONE of the following:
|
11
|
+
|
12
|
+
a) place your modifications in the Public Domain or otherwise
|
13
|
+
make them Freely Available, such as by posting said
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
15
|
+
the author to include your modifications in the software.
|
16
|
+
|
17
|
+
b) use the modified software only within your corporation or
|
18
|
+
organization.
|
19
|
+
|
20
|
+
c) give non-standard binaries non-standard names, with
|
21
|
+
instructions on where to get the original software distribution.
|
22
|
+
|
23
|
+
d) make other distribution arrangements with the author.
|
24
|
+
|
25
|
+
3. You may distribute the software in object code or binary form,
|
26
|
+
provided that you do at least ONE of the following:
|
27
|
+
|
28
|
+
a) distribute the binaries and library files of the software,
|
29
|
+
together with instructions (in the manual page or equivalent)
|
30
|
+
on where to get the original distribution.
|
31
|
+
|
32
|
+
b) accompany the distribution with the machine-readable source of
|
33
|
+
the software.
|
34
|
+
|
35
|
+
c) give non-standard binaries non-standard names, with
|
36
|
+
instructions on where to get the original software distribution.
|
37
|
+
|
38
|
+
d) make other distribution arrangements with the author.
|
39
|
+
|
40
|
+
4. You may modify and include the part of the software into any other
|
41
|
+
software (possibly commercial). But some files in the distribution
|
42
|
+
are not written by the author, so that they are not under these terms.
|
43
|
+
|
44
|
+
For the list of those files and their copying conditions, see the
|
45
|
+
file LEGAL.
|
46
|
+
|
47
|
+
5. The scripts and library files supplied as input to or produced as
|
48
|
+
output from the software do not automatically fall under the
|
49
|
+
copyright of the software, but belong to whomever generated them,
|
50
|
+
and may be sold commercially, and may be aggregated with this
|
51
|
+
software.
|
52
|
+
|
53
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
54
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
55
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
56
|
+
PURPOSE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
History.txt
|
2
|
+
License.txt
|
3
|
+
Manifest.txt
|
4
|
+
README.txt
|
5
|
+
Rakefile
|
6
|
+
bin/lwws
|
7
|
+
config/hoe.rb
|
8
|
+
config/requirements.rb
|
9
|
+
lib/weatherhacks.rb
|
10
|
+
lib/weatherhacks/forecastmap.rb
|
11
|
+
lib/weatherhacks/lwws.rb
|
12
|
+
lib/weatherhacks/version.rb
|
13
|
+
misc/forecastmap.xsl
|
14
|
+
script/destroy
|
15
|
+
script/generate
|
16
|
+
script/txt2html
|
17
|
+
setup.rb
|
18
|
+
spec/lwws_spec.rb
|
19
|
+
spec/spec.opts
|
20
|
+
spec/spec_helper.rb
|
21
|
+
tasks/deployment.rake
|
22
|
+
tasks/environment.rake
|
23
|
+
tasks/rspec.rake
|
24
|
+
tasks/weatherhacks.rake
|
25
|
+
tasks/website.rake
|
26
|
+
website/index.html
|
27
|
+
website/index.txt
|
28
|
+
website/javascripts/rounded_corners_lite.inc.js
|
29
|
+
website/stylesheets/screen.css
|
30
|
+
website/template.rhtml
|
data/README.txt
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
README for ruby-weatherhacks
|
2
|
+
============================
|
3
|
+
ruby-weatherhacks is a wrapper library for livdoor WeatherHacks API.
|
4
|
+
|
5
|
+
livedoor ... http://www.livedoor.com/
|
6
|
+
WeatherHacks ... http://weather.livedoor.com/weather_hacks/
|
7
|
+
|
8
|
+
Copyright (C) 2007 Keita Yamaguchi
|
9
|
+
Mail: keita.yamaguchi@gmail.com
|
data/Rakefile
ADDED
data/bin/lwws
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby -Ku
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "weatherhacks"
|
5
|
+
rescue LoadError
|
6
|
+
require "rubygems"
|
7
|
+
require "weatherhacks"
|
8
|
+
end
|
9
|
+
|
10
|
+
require "optparse"
|
11
|
+
|
12
|
+
OptionParser.new do |opt|
|
13
|
+
opt.on("--list") do
|
14
|
+
$mode = :list
|
15
|
+
end
|
16
|
+
opt.parse!
|
17
|
+
end
|
18
|
+
|
19
|
+
def temperature(forecast)
|
20
|
+
line = []
|
21
|
+
if forecast.celsius.min
|
22
|
+
line << "最低気温" + forecast.celsius.min.to_s + "度"
|
23
|
+
end
|
24
|
+
if forecast.celsius.max
|
25
|
+
line << "最高気温" + forecast.celsius.max.to_s + "度"
|
26
|
+
end
|
27
|
+
"(" + line.join(", ") + ")"
|
28
|
+
end
|
29
|
+
|
30
|
+
def show_forecast
|
31
|
+
today = WeatherHacks::LWWS.request($city.id, :today)
|
32
|
+
tomorrow = WeatherHacks::LWWS.request($city.id, :tomorrow)
|
33
|
+
dayaftertomorrow = WeatherHacks::LWWS.request($city.id, :dayaftertomorrow)
|
34
|
+
puts <<LOCATION
|
35
|
+
#{today.location.area}地方/#{today.location.pref}/#{today.location.city}
|
36
|
+
今日: #{today.telop}#{temperature(today)}
|
37
|
+
明日: #{tomorrow.telop}#{temperature(tomorrow)}
|
38
|
+
明後日: #{dayaftertomorrow.telop}#{temperature(dayaftertomorrow)}
|
39
|
+
LOCATION
|
40
|
+
end
|
41
|
+
|
42
|
+
case $mode
|
43
|
+
when :list
|
44
|
+
WeatherHacks::ForecastMap::AREAS.each do |area|
|
45
|
+
puts "[#{area.name}]"
|
46
|
+
area.prefs.each do |pref|
|
47
|
+
puts "#{pref.name}: " + pref.cities.map{|city| city.name}.join(", ")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
else
|
51
|
+
if ARGV[0] and WeatherHacks::ForecastMap::CITY.has_key?(ARGV[0])
|
52
|
+
$city = WeatherHacks::ForecastMap::CITY[ARGV[0]]
|
53
|
+
else
|
54
|
+
puts "Unknown city name: " + ARGV[0]
|
55
|
+
exit 0
|
56
|
+
end
|
57
|
+
show_forecast
|
58
|
+
end
|
data/config/hoe.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'weatherhacks/version'
|
2
|
+
|
3
|
+
AUTHOR = 'Keita Yamaguchi' # can also be an array of Authors
|
4
|
+
EMAIL = "keita.yamaguchi@gmail.com"
|
5
|
+
DESCRIPTION = "description of gem"
|
6
|
+
GEM_NAME = 'weatherhacks' # what ppl will type to install your gem
|
7
|
+
RUBYFORGE_PROJECT = 'weatherhacks' # The unix name for your project
|
8
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
9
|
+
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
10
|
+
|
11
|
+
@config_file = "~/.rubyforge/user-config.yml"
|
12
|
+
@config = nil
|
13
|
+
RUBYFORGE_USERNAME = "unknown"
|
14
|
+
def rubyforge_username
|
15
|
+
unless @config
|
16
|
+
begin
|
17
|
+
@config = YAML.load(File.read(File.expand_path(@config_file)))
|
18
|
+
rescue
|
19
|
+
puts <<-EOS
|
20
|
+
ERROR: No rubyforge config file found: #{@config_file}
|
21
|
+
Run 'rubyforge setup' to prepare your env for access to Rubyforge
|
22
|
+
- See http://newgem.rubyforge.org/rubyforge.html for more details
|
23
|
+
EOS
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
RUBYFORGE_USERNAME.replace @config["username"]
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
REV = nil
|
32
|
+
# UNCOMMENT IF REQUIRED:
|
33
|
+
# REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
|
34
|
+
VERS = WeatherHacks::VERSION::STRING + (REV ? ".#{REV}" : "")
|
35
|
+
RDOC_OPTS = ['--quiet', '--title', 'weatherhacks documentation',
|
36
|
+
"--opname", "index.html",
|
37
|
+
"--line-numbers",
|
38
|
+
"--main", "README",
|
39
|
+
"--inline-source"]
|
40
|
+
|
41
|
+
class Hoe
|
42
|
+
def extra_deps
|
43
|
+
@extra_deps.reject! { |x| Array(x).first == 'hoe' }
|
44
|
+
@extra_deps
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Generate all the Rake tasks
|
49
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
50
|
+
hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
51
|
+
p.author = AUTHOR
|
52
|
+
p.description = DESCRIPTION
|
53
|
+
p.email = EMAIL
|
54
|
+
p.summary = DESCRIPTION
|
55
|
+
p.url = HOMEPATH
|
56
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
57
|
+
p.test_globs = ["test/**/test_*.rb"]
|
58
|
+
p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
|
59
|
+
|
60
|
+
# == Optional
|
61
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
62
|
+
#p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
63
|
+
|
64
|
+
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
|
69
|
+
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
70
|
+
hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
|
71
|
+
hoe.rsync_args = '-av --delete --ignore-errors'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
include FileUtils
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
%w[rake hoe newgem rubigen].each do |req_gem|
|
6
|
+
begin
|
7
|
+
require req_gem
|
8
|
+
rescue LoadError
|
9
|
+
puts "This Rakefile requires the '#{req_gem}' RubyGem."
|
10
|
+
puts "Installation: gem install #{req_gem} -y"
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
$:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
|
16
|
+
|
17
|
+
require 'weatherhacks'
|
@@ -0,0 +1,266 @@
|
|
1
|
+
module WeatherHacks
|
2
|
+
module ForecastMap
|
3
|
+
area("北海道地方", "http://weather.livedoor.com/forecast/rss/1.xml") do
|
4
|
+
pref("道北") do
|
5
|
+
city("稚内", 1, "http://weather.livedoor.com/forecast/rss/1a/1.xml")
|
6
|
+
city("旭川", 2, "http://weather.livedoor.com/forecast/rss/1a/2.xml")
|
7
|
+
city("留萌", 3, "http://weather.livedoor.com/forecast/rss/1a/3.xml")
|
8
|
+
end
|
9
|
+
pref("道央") do
|
10
|
+
city("札幌", 4, "http://weather.livedoor.com/forecast/rss/1b/4.xml")
|
11
|
+
city("岩見沢", 5, "http://weather.livedoor.com/forecast/rss/1b/5.xml")
|
12
|
+
city("倶知安", 6, "http://weather.livedoor.com/forecast/rss/1b/6.xml")
|
13
|
+
end
|
14
|
+
pref("道東") do
|
15
|
+
city("網走", 7, "http://weather.livedoor.com/forecast/rss/1c/7.xml")
|
16
|
+
city("北見", 8, "http://weather.livedoor.com/forecast/rss/1c/8.xml")
|
17
|
+
city("紋別", 9, "http://weather.livedoor.com/forecast/rss/1c/9.xml")
|
18
|
+
city("根室", 10, "http://weather.livedoor.com/forecast/rss/1c/10.xml")
|
19
|
+
city("釧路", 11, "http://weather.livedoor.com/forecast/rss/1c/11.xml")
|
20
|
+
city("帯広", 12, "http://weather.livedoor.com/forecast/rss/1c/12.xml")
|
21
|
+
end
|
22
|
+
pref("道南") do
|
23
|
+
city("室蘭", 13, "http://weather.livedoor.com/forecast/rss/1d/13.xml")
|
24
|
+
city("浦河", 14, "http://weather.livedoor.com/forecast/rss/1d/14.xml")
|
25
|
+
city("函館", 15, "http://weather.livedoor.com/forecast/rss/1d/15.xml")
|
26
|
+
city("江差", 16, "http://weather.livedoor.com/forecast/rss/1d/16.xml")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
area("東北地方", "http://weather.livedoor.com/forecast/rss/2.xml") do
|
30
|
+
pref("青森県") do
|
31
|
+
city("青森", 17, "http://weather.livedoor.com/forecast/rss/2/17.xml")
|
32
|
+
city("むつ", 18, "http://weather.livedoor.com/forecast/rss/2/18.xml")
|
33
|
+
city("八戸", 19, "http://weather.livedoor.com/forecast/rss/2/19.xml")
|
34
|
+
end
|
35
|
+
pref("秋田県") do
|
36
|
+
city("秋田", 20, "http://weather.livedoor.com/forecast/rss/5/20.xml")
|
37
|
+
city("横手", 21, "http://weather.livedoor.com/forecast/rss/5/21.xml")
|
38
|
+
end
|
39
|
+
pref("岩手県") do
|
40
|
+
city("盛岡", 22, "http://weather.livedoor.com/forecast/rss/3/22.xml")
|
41
|
+
city("宮古", 23, "http://weather.livedoor.com/forecast/rss/3/23.xml")
|
42
|
+
city("大船渡", 24, "http://weather.livedoor.com/forecast/rss/3/24.xml")
|
43
|
+
end
|
44
|
+
pref("宮城県") do
|
45
|
+
city("仙台", 25, "http://weather.livedoor.com/forecast/rss/4/25.xml")
|
46
|
+
city("白石", 26, "http://weather.livedoor.com/forecast/rss/4/26.xml")
|
47
|
+
end
|
48
|
+
pref("山形県") do
|
49
|
+
city("山形", 27, "http://weather.livedoor.com/forecast/rss/6/27.xml")
|
50
|
+
city("米沢", 28, "http://weather.livedoor.com/forecast/rss/6/28.xml")
|
51
|
+
city("酒田", 29, "http://weather.livedoor.com/forecast/rss/6/29.xml")
|
52
|
+
city("新庄", 30, "http://weather.livedoor.com/forecast/rss/6/30.xml")
|
53
|
+
end
|
54
|
+
pref("福島県") do
|
55
|
+
city("福島", 31, "http://weather.livedoor.com/forecast/rss/7/31.xml")
|
56
|
+
city("小名浜", 32, "http://weather.livedoor.com/forecast/rss/7/32.xml")
|
57
|
+
city("若松", 33, "http://weather.livedoor.com/forecast/rss/7/33.xml")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
area("関東地方", "http://weather.livedoor.com/forecast/rss/3.xml") do
|
61
|
+
pref("茨城県") do
|
62
|
+
city("水戸", 54, "http://weather.livedoor.com/forecast/rss/8/54.xml")
|
63
|
+
city("土浦", 55, "http://weather.livedoor.com/forecast/rss/8/55.xml")
|
64
|
+
end
|
65
|
+
pref("栃木県") do
|
66
|
+
city("宇都宮", 56, "http://weather.livedoor.com/forecast/rss/9/56.xml")
|
67
|
+
city("大田原", 57, "http://weather.livedoor.com/forecast/rss/9/57.xml")
|
68
|
+
end
|
69
|
+
pref("群馬県") do
|
70
|
+
city("前橋", 58, "http://weather.livedoor.com/forecast/rss/10/58.xml")
|
71
|
+
city("みなかみ", 59, "http://weather.livedoor.com/forecast/rss/10/59.xml")
|
72
|
+
end
|
73
|
+
pref("埼玉県") do
|
74
|
+
city("さいたま", 60, "http://weather.livedoor.com/forecast/rss/11/60.xml")
|
75
|
+
city("熊谷", 61, "http://weather.livedoor.com/forecast/rss/11/61.xml")
|
76
|
+
city("秩父", 62, "http://weather.livedoor.com/forecast/rss/11/62.xml")
|
77
|
+
end
|
78
|
+
pref("東京都") do
|
79
|
+
city("東京", 63, "http://weather.livedoor.com/forecast/rss/13/63.xml")
|
80
|
+
city("大島", 64, "http://weather.livedoor.com/forecast/rss/13/64.xml")
|
81
|
+
city("八丈島", 65, "http://weather.livedoor.com/forecast/rss/13/65.xml")
|
82
|
+
city("父島", 66, "http://weather.livedoor.com/forecast/rss/13/66.xml")
|
83
|
+
end
|
84
|
+
pref("千葉県") do
|
85
|
+
city("千葉", 67, "http://weather.livedoor.com/forecast/rss/12/67.xml")
|
86
|
+
city("銚子", 68, "http://weather.livedoor.com/forecast/rss/12/68.xml")
|
87
|
+
city("館山", 69, "http://weather.livedoor.com/forecast/rss/12/69.xml")
|
88
|
+
end
|
89
|
+
pref("神奈川県") do
|
90
|
+
city("横浜", 70, "http://weather.livedoor.com/forecast/rss/14/70.xml")
|
91
|
+
city("小田原", 71, "http://weather.livedoor.com/forecast/rss/14/71.xml")
|
92
|
+
end
|
93
|
+
pref("山梨県") do
|
94
|
+
city("甲府", 75, "http://weather.livedoor.com/forecast/rss/19/75.xml")
|
95
|
+
city("河口湖", 76, "http://weather.livedoor.com/forecast/rss/19/76.xml")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
area("信越・北陸地方", "http://weather.livedoor.com/forecast/rss/4.xml") do
|
99
|
+
pref("富山県") do
|
100
|
+
city("富山", 44, "http://weather.livedoor.com/forecast/rss/16/44.xml")
|
101
|
+
city("伏木", 45, "http://weather.livedoor.com/forecast/rss/16/45.xml")
|
102
|
+
end
|
103
|
+
pref("石川県") do
|
104
|
+
city("金沢", 46, "http://weather.livedoor.com/forecast/rss/17/46.xml")
|
105
|
+
city("輪島", 47, "http://weather.livedoor.com/forecast/rss/17/47.xml")
|
106
|
+
end
|
107
|
+
pref("福井県") do
|
108
|
+
city("福井", 48, "http://weather.livedoor.com/forecast/rss/18/48.xml")
|
109
|
+
city("敦賀", 49, "http://weather.livedoor.com/forecast/rss/18/49.xml")
|
110
|
+
end
|
111
|
+
pref("新潟県") do
|
112
|
+
city("新潟", 50, "http://weather.livedoor.com/forecast/rss/15/50.xml")
|
113
|
+
city("長岡", 51, "http://weather.livedoor.com/forecast/rss/15/51.xml")
|
114
|
+
city("高田", 52, "http://weather.livedoor.com/forecast/rss/15/52.xml")
|
115
|
+
city("相川", 53, "http://weather.livedoor.com/forecast/rss/15/53.xml")
|
116
|
+
end
|
117
|
+
pref("長野県") do
|
118
|
+
city("長野", 72, "http://weather.livedoor.com/forecast/rss/20/72.xml")
|
119
|
+
city("松本", 73, "http://weather.livedoor.com/forecast/rss/20/73.xml")
|
120
|
+
city("飯田", 74, "http://weather.livedoor.com/forecast/rss/20/74.xml")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
area("東海地方", "http://weather.livedoor.com/forecast/rss/5.xml") do
|
124
|
+
pref("静岡県") do
|
125
|
+
city("静岡", 34, "http://weather.livedoor.com/forecast/rss/22/34.xml")
|
126
|
+
city("網代", 35, "http://weather.livedoor.com/forecast/rss/22/35.xml")
|
127
|
+
city("三島", 36, "http://weather.livedoor.com/forecast/rss/22/36.xml")
|
128
|
+
city("浜松", 37, "http://weather.livedoor.com/forecast/rss/22/37.xml")
|
129
|
+
end
|
130
|
+
pref("愛知県") do
|
131
|
+
city("名古屋", 38, "http://weather.livedoor.com/forecast/rss/23/38.xml")
|
132
|
+
city("豊橋", 39, "http://weather.livedoor.com/forecast/rss/23/39.xml")
|
133
|
+
end
|
134
|
+
pref("岐阜県") do
|
135
|
+
city("岐阜", 40, "http://weather.livedoor.com/forecast/rss/21/40.xml")
|
136
|
+
city("高山", 41, "http://weather.livedoor.com/forecast/rss/21/41.xml")
|
137
|
+
end
|
138
|
+
pref("三重県") do
|
139
|
+
city("津", 42, "http://weather.livedoor.com/forecast/rss/24/42.xml")
|
140
|
+
city("尾鷲", 43, "http://weather.livedoor.com/forecast/rss/24/43.xml")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
area("近畿地方", "http://weather.livedoor.com/forecast/rss/6.xml") do
|
144
|
+
pref("滋賀県") do
|
145
|
+
city("大津", 77, "http://weather.livedoor.com/forecast/rss/25/77.xml")
|
146
|
+
city("彦根", 78, "http://weather.livedoor.com/forecast/rss/25/78.xml")
|
147
|
+
end
|
148
|
+
pref("京都府") do
|
149
|
+
city("京都", 79, "http://weather.livedoor.com/forecast/rss/26/79.xml")
|
150
|
+
city("舞鶴", 80, "http://weather.livedoor.com/forecast/rss/26/80.xml")
|
151
|
+
end
|
152
|
+
pref("大阪府") do
|
153
|
+
city("大阪", 81, "http://weather.livedoor.com/forecast/rss/27/81.xml")
|
154
|
+
end
|
155
|
+
pref("兵庫県") do
|
156
|
+
city("神戸", 82, "http://weather.livedoor.com/forecast/rss/28/82.xml")
|
157
|
+
city("豊岡", 83, "http://weather.livedoor.com/forecast/rss/28/83.xml")
|
158
|
+
end
|
159
|
+
pref("奈良県") do
|
160
|
+
city("奈良", 84, "http://weather.livedoor.com/forecast/rss/29/84.xml")
|
161
|
+
city("風屋", 85, "http://weather.livedoor.com/forecast/rss/29/85.xml")
|
162
|
+
end
|
163
|
+
pref("和歌山県") do
|
164
|
+
city("和歌山", 86, "http://weather.livedoor.com/forecast/rss/30/86.xml")
|
165
|
+
city("潮岬", 87, "http://weather.livedoor.com/forecast/rss/30/87.xml")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
area("中国地方", "http://weather.livedoor.com/forecast/rss/7.xml") do
|
169
|
+
pref("岡山県") do
|
170
|
+
city("岡山", 88, "http://weather.livedoor.com/forecast/rss/33/88.xml")
|
171
|
+
city("津山", 89, "http://weather.livedoor.com/forecast/rss/33/89.xml")
|
172
|
+
end
|
173
|
+
pref("広島県") do
|
174
|
+
city("広島", 90, "http://weather.livedoor.com/forecast/rss/34/90.xml")
|
175
|
+
city("庄原", 91, "http://weather.livedoor.com/forecast/rss/34/91.xml")
|
176
|
+
end
|
177
|
+
pref("島根県") do
|
178
|
+
city("松江", 92, "http://weather.livedoor.com/forecast/rss/32/92.xml")
|
179
|
+
city("浜田", 93, "http://weather.livedoor.com/forecast/rss/32/93.xml")
|
180
|
+
city("西郷", 94, "http://weather.livedoor.com/forecast/rss/32/94.xml")
|
181
|
+
end
|
182
|
+
pref("鳥取県") do
|
183
|
+
city("鳥取", 95, "http://weather.livedoor.com/forecast/rss/31/95.xml")
|
184
|
+
city("米子", 96, "http://weather.livedoor.com/forecast/rss/31/96.xml")
|
185
|
+
end
|
186
|
+
pref("山口県") do
|
187
|
+
city("下関", 97, "http://weather.livedoor.com/forecast/rss/35/97.xml")
|
188
|
+
city("山口", 98, "http://weather.livedoor.com/forecast/rss/35/98.xml")
|
189
|
+
city("柳井", 99, "http://weather.livedoor.com/forecast/rss/35/99.xml")
|
190
|
+
city("萩", 100, "http://weather.livedoor.com/forecast/rss/35/100.xml")
|
191
|
+
end
|
192
|
+
end
|
193
|
+
area("四国地方", "http://weather.livedoor.com/forecast/rss/8.xml") do
|
194
|
+
pref("徳島県") do
|
195
|
+
city("徳島", 101, "http://weather.livedoor.com/forecast/rss/36/101.xml")
|
196
|
+
city("日和佐", 102, "http://weather.livedoor.com/forecast/rss/36/102.xml")
|
197
|
+
end
|
198
|
+
pref("香川県") do
|
199
|
+
city("高松", 103, "http://weather.livedoor.com/forecast/rss/37/103.xml")
|
200
|
+
end
|
201
|
+
pref("愛媛県") do
|
202
|
+
city("松山", 104, "http://weather.livedoor.com/forecast/rss/38/104.xml")
|
203
|
+
city("新居浜", 105, "http://weather.livedoor.com/forecast/rss/38/105.xml")
|
204
|
+
city("宇和島", 106, "http://weather.livedoor.com/forecast/rss/38/106.xml")
|
205
|
+
end
|
206
|
+
pref("高知県") do
|
207
|
+
city("高知", 107, "http://weather.livedoor.com/forecast/rss/39/107.xml")
|
208
|
+
city("室戸", 108, "http://weather.livedoor.com/forecast/rss/39/108.xml")
|
209
|
+
city("清水", 109, "http://weather.livedoor.com/forecast/rss/39/109.xml")
|
210
|
+
end
|
211
|
+
end
|
212
|
+
area("九州地方", "http://weather.livedoor.com/forecast/rss/9.xml") do
|
213
|
+
pref("福岡県") do
|
214
|
+
city("福岡", 110, "http://weather.livedoor.com/forecast/rss/40/110.xml")
|
215
|
+
city("八幡", 111, "http://weather.livedoor.com/forecast/rss/40/111.xml")
|
216
|
+
city("飯塚", 112, "http://weather.livedoor.com/forecast/rss/40/112.xml")
|
217
|
+
city("久留米", 113, "http://weather.livedoor.com/forecast/rss/40/113.xml")
|
218
|
+
end
|
219
|
+
pref("大分県") do
|
220
|
+
city("大分", 114, "http://weather.livedoor.com/forecast/rss/44/114.xml")
|
221
|
+
city("中津", 115, "http://weather.livedoor.com/forecast/rss/44/115.xml")
|
222
|
+
city("日田", 116, "http://weather.livedoor.com/forecast/rss/44/116.xml")
|
223
|
+
city("佐伯", 117, "http://weather.livedoor.com/forecast/rss/44/117.xml")
|
224
|
+
end
|
225
|
+
pref("長崎県") do
|
226
|
+
city("長崎", 118, "http://weather.livedoor.com/forecast/rss/42/118.xml")
|
227
|
+
city("佐世保", 119, "http://weather.livedoor.com/forecast/rss/42/119.xml")
|
228
|
+
city("厳原", 120, "http://weather.livedoor.com/forecast/rss/42/120.xml")
|
229
|
+
city("福江", 121, "http://weather.livedoor.com/forecast/rss/42/121.xml")
|
230
|
+
end
|
231
|
+
pref("佐賀県") do
|
232
|
+
city("佐賀", 122, "http://weather.livedoor.com/forecast/rss/41/122.xml")
|
233
|
+
city("伊万里", 123, "http://weather.livedoor.com/forecast/rss/41/123.xml")
|
234
|
+
end
|
235
|
+
pref("熊本県") do
|
236
|
+
city("熊本", 124, "http://weather.livedoor.com/forecast/rss/43/124.xml")
|
237
|
+
city("阿蘇乙姫", 125, "http://weather.livedoor.com/forecast/rss/43/125.xml")
|
238
|
+
city("牛深", 126, "http://weather.livedoor.com/forecast/rss/43/126.xml")
|
239
|
+
city("人吉", 127, "http://weather.livedoor.com/forecast/rss/43/127.xml")
|
240
|
+
end
|
241
|
+
pref("宮崎県") do
|
242
|
+
city("宮崎", 128, "http://weather.livedoor.com/forecast/rss/45/128.xml")
|
243
|
+
city("延岡", 129, "http://weather.livedoor.com/forecast/rss/45/129.xml")
|
244
|
+
city("都城", 130, "http://weather.livedoor.com/forecast/rss/45/130.xml")
|
245
|
+
city("高千穂", 131, "http://weather.livedoor.com/forecast/rss/45/131.xml")
|
246
|
+
end
|
247
|
+
pref("鹿児島県") do
|
248
|
+
city("鹿児島", 132, "http://weather.livedoor.com/forecast/rss/46/132.xml")
|
249
|
+
city("鹿屋", 133, "http://weather.livedoor.com/forecast/rss/46/133.xml")
|
250
|
+
city("種子島", 134, "http://weather.livedoor.com/forecast/rss/46/134.xml")
|
251
|
+
city("名瀬", 135, "http://weather.livedoor.com/forecast/rss/46/135.xml")
|
252
|
+
end
|
253
|
+
end
|
254
|
+
area("南西諸島地方", "http://weather.livedoor.com/forecast/rss/10.xml") do
|
255
|
+
pref("沖縄県") do
|
256
|
+
city("那覇", 136, "http://weather.livedoor.com/forecast/rss/47/136.xml")
|
257
|
+
city("名護", 137, "http://weather.livedoor.com/forecast/rss/47/137.xml")
|
258
|
+
city("久米島", 138, "http://weather.livedoor.com/forecast/rss/47/138.xml")
|
259
|
+
city("南大東島", 139, "http://weather.livedoor.com/forecast/rss/47/139.xml")
|
260
|
+
city("宮古島", 140, "http://weather.livedoor.com/forecast/rss/47/140.xml")
|
261
|
+
city("石垣島", 141, "http://weather.livedoor.com/forecast/rss/47/141.xml")
|
262
|
+
city("与那国島", 142, "http://weather.livedoor.com/forecast/rss/47/142.xml")
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "rexml/document"
|
3
|
+
require "net/http"
|
4
|
+
require "time"
|
5
|
+
|
6
|
+
module WeatherHacks::LWWS
|
7
|
+
URL = URI.parse("http://weather.livedoor.com/forecast/webservice/rest/v1")
|
8
|
+
|
9
|
+
def self.path(city_id, day) #:nodoc:
|
10
|
+
URL.path + "?city=#{city_id}&day=#{day}"
|
11
|
+
end
|
12
|
+
|
13
|
+
class Error < StandardError
|
14
|
+
attr_reader :res
|
15
|
+
def initialize(res)
|
16
|
+
@res = res
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Forecast
|
21
|
+
attr_reader :author, :location, :title, :link, :forecastday, :day
|
22
|
+
attr_reader :forecastdate, :publictime, :telop, :description, :image
|
23
|
+
attr_reader :celsius, :fahrenheit, :pinpoints, :copyright
|
24
|
+
|
25
|
+
def initialize(doc)
|
26
|
+
raise ArgumentError, doc unless doc.kind_of? REXML::Document
|
27
|
+
elt = doc.root.elements["/lwws"]
|
28
|
+
@author = elt.elements["author"].text
|
29
|
+
@location = Location.new(elt.elements["location"])
|
30
|
+
@title = elt.elements["title"].text
|
31
|
+
@link = URI.parse(elt.elements["link"].text)
|
32
|
+
@forecastday = elt.elements["forecastday"].text
|
33
|
+
@day = elt.elements["day"].text
|
34
|
+
@forecastdate = Time.parse(elt.elements["forecastdate"].text)
|
35
|
+
@publictime = Time.parse(elt.elements["publictime"].text)
|
36
|
+
@telop = elt.elements["telop"].text
|
37
|
+
@description = elt.elements["description"].text
|
38
|
+
@image = Image.new(elt.elements["image"])
|
39
|
+
@celsius, @fahrenheit = Temperature.create(elt.elements["temperature"])
|
40
|
+
@pinpoints = Array.new
|
41
|
+
elt.elements.collect("pinpoint/location") do |node|
|
42
|
+
@pinpoints << PinpointLocation.new(node)
|
43
|
+
end
|
44
|
+
@copyright = Copyright.new(elt.elements["copyright"])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Location
|
49
|
+
attr_reader :city, :area, :pref
|
50
|
+
def initialize(elt)
|
51
|
+
@area = elt.attributes["area"]
|
52
|
+
@pref = elt.attributes["pref"]
|
53
|
+
@city = elt.attributes["city"]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class Image
|
58
|
+
attr_reader :title, :link, :url, :width, :height
|
59
|
+
def initialize(elt)
|
60
|
+
@title = elt.elements["title"].text
|
61
|
+
@link = URI.parse(elt.elements["link"].text)
|
62
|
+
@url = URI.parse(elt.elements["url"].text)
|
63
|
+
@width = elt.elements["width"].text.to_i
|
64
|
+
@height = elt.elements["height"].text.to_i
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Temperature
|
69
|
+
attr_reader :max, :min
|
70
|
+
def self.create(elt)
|
71
|
+
return Celsius.new(elt), Fahrenheit.new(elt)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Celsius < Temperature
|
76
|
+
def initialize(elt)
|
77
|
+
max = elt.elements["max/celsius"].text
|
78
|
+
@max = max.to_i if max
|
79
|
+
min = elt.elements["min/celsius"].text
|
80
|
+
@max = min.to_i if min
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class Fahrenheit < Temperature
|
85
|
+
def initialize(elt)
|
86
|
+
max = elt.elements["max/fahrenheit"].text
|
87
|
+
@max = max.to_f if max
|
88
|
+
min = elt.elements["min/fahrenheit"].text
|
89
|
+
@max = min.to_f if min
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class PinpointLocation
|
94
|
+
attr_reader :title, :link, :publictime
|
95
|
+
def initialize(elt)
|
96
|
+
raise ArgumentError, elt unless elt.kind_of? REXML::Element
|
97
|
+
@title = elt.elements["title"].text
|
98
|
+
@link = URI.parse(elt.elements["link"].text)
|
99
|
+
@publictime = Time.parse(elt.elements["publictime"].text)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class Copyright
|
104
|
+
attr_reader :title, :link, :image, :providers
|
105
|
+
def initialize(elt)
|
106
|
+
@title = elt.elements["title"].text
|
107
|
+
@link = URI.parse(elt.elements["link"].text)
|
108
|
+
@image = Image.new(elt.elements["image"])
|
109
|
+
@providers = Array.new
|
110
|
+
elt.each_element("provider") do |provider|
|
111
|
+
@providers << Provider.new(provider)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class Provider
|
117
|
+
attr_reader :name, :link
|
118
|
+
def initialize(elt)
|
119
|
+
@name = elt.attributes["name"]
|
120
|
+
@link = URI.parse(elt.attributes["link"])
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Returns a Forecast object.
|
125
|
+
# city_id:: city id
|
126
|
+
# day:: :today, :tomorrow or :dayaftertomorrow
|
127
|
+
def self.request(city_id, day = :today)
|
128
|
+
unless day == :today or day == :tomorrow or day == :dayaftertomorrow
|
129
|
+
raise ArgumentError, day
|
130
|
+
end
|
131
|
+
req = Net::HTTP::Get.new(path(city_id, day.to_s))
|
132
|
+
http = Net::HTTP.new(URL.host)
|
133
|
+
case res = http.request(req)
|
134
|
+
when Net::HTTPSuccess
|
135
|
+
Forecast.new(REXML::Document.new(res.body))
|
136
|
+
else
|
137
|
+
raise Error.new(res)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|