weatherhacks 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.
- 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
|