WIshMailer 0.11.25
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +3 -0
- data/README +3 -0
- data/Rakefile +45 -0
- data/bin/wishmailer +192 -0
- data/bin/wm.yaml +15 -0
- data/lib/WishMailer.rb +105 -0
- data/lib/feature/ContentControl.rb +36 -0
- data/lib/feature/GoogleMovie.rb +52 -0
- data/lib/feature/GoogleWeather.rb +102 -0
- data/lib/feature/TodayInHistory.rb +54 -0
- data/lib/main.rb +42 -0
- data/log/wish_mailer.log +0 -0
- metadata +67 -0
data/LICENSE
ADDED
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#
|
2
|
+
# To change this template, choose Tools | Templates
|
3
|
+
# and open the template in the editor.
|
4
|
+
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'rake'
|
8
|
+
require 'rake/clean'
|
9
|
+
require 'rake/gempackagetask'
|
10
|
+
require 'rake/rdoctask'
|
11
|
+
require 'rake/testtask'
|
12
|
+
|
13
|
+
spec = Gem::Specification.new do |s|
|
14
|
+
s.name = 'WIshMailer'
|
15
|
+
s.version = '0.11.25'
|
16
|
+
s.has_rdoc = false
|
17
|
+
s.extra_rdoc_files = ['README', 'LICENSE']
|
18
|
+
s.summary = 'Wish from heart,to best friend.'
|
19
|
+
s.description = s.summary
|
20
|
+
s.author = 'CharlesCui'
|
21
|
+
s.email = 'zheng.cuizh@gmail.com'
|
22
|
+
s.executables = ['wishmailer']
|
23
|
+
s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec,log}/**/*")
|
24
|
+
s.require_path = "lib"
|
25
|
+
s.bindir = "bin"
|
26
|
+
end
|
27
|
+
|
28
|
+
Rake::GemPackageTask.new(spec) do |p|
|
29
|
+
p.gem_spec = spec
|
30
|
+
p.need_tar = true
|
31
|
+
p.need_zip = true
|
32
|
+
end
|
33
|
+
|
34
|
+
Rake::RDocTask.new do |rdoc|
|
35
|
+
files =['README', 'LICENSE', 'lib/**/*.rb']
|
36
|
+
rdoc.rdoc_files.add(files)
|
37
|
+
rdoc.main = "README" # page to start on
|
38
|
+
rdoc.title = "WIshMailer Docs"
|
39
|
+
rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
|
40
|
+
rdoc.options << '--line-numbers'
|
41
|
+
end
|
42
|
+
|
43
|
+
Rake::TestTask.new do |t|
|
44
|
+
t.test_files = FileList['test/**/*.rb']
|
45
|
+
end
|
data/bin/wishmailer
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2009, Charles Cui
|
5
|
+
# All rights reserved. Licensed under the BSD license. See LICENSE for details
|
6
|
+
#++
|
7
|
+
|
8
|
+
# $: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
|
9
|
+
require 'rubygems'
|
10
|
+
require 'optparse'
|
11
|
+
require "logger"
|
12
|
+
|
13
|
+
require File.join(File.dirname(__FILE__),"..","lib","WishMailer.rb")
|
14
|
+
|
15
|
+
$WMHeader = nil
|
16
|
+
$WMBottom = nil
|
17
|
+
|
18
|
+
#-----------------------------Params Construct---------------------------------#
|
19
|
+
|
20
|
+
vars = {}
|
21
|
+
ARGV.options do
|
22
|
+
|opts|
|
23
|
+
opts.banner = <<DOC
|
24
|
+
WishMailer :
|
25
|
+
Mail/Gtalk: zheng.cuizh@gmail.com
|
26
|
+
|
27
|
+
Usage: #{File.basename($0)} [options] argv...
|
28
|
+
BestUsage: crontab ......
|
29
|
+
DOC
|
30
|
+
|
31
|
+
opts.on_head("WishMailer optins useage:")
|
32
|
+
|
33
|
+
vars[:wmyaml] = nil
|
34
|
+
opts.on("-f", "--wmyaml=./wish_mail.yaml","*", String,
|
35
|
+
"It's important.","Other params will be ignored if given this.","The Example yaml file is "+File.expand_path(File.join(File.dirname(__FILE__),'wm.yaml'))) {|vars[:wmyaml]|}
|
36
|
+
|
37
|
+
opts.on("-s", "--sender=zheng.cuizh@gmail.com","*", String,
|
38
|
+
"who sende this wish mail.") {|vars[:sender]|}
|
39
|
+
|
40
|
+
# separater
|
41
|
+
opts.on()
|
42
|
+
|
43
|
+
opts.on("-S","--smtp=smtp.163.com","*", String,
|
44
|
+
"the smtp server.") {|vars[:smtp]|}
|
45
|
+
|
46
|
+
opts.on("-a", "--auth=login","*", String,
|
47
|
+
"one of [plain,login,cram_md5] is OK.") {|vars[:auth]|}
|
48
|
+
|
49
|
+
opts.on("-r","--receiver=[zheng.cuizh@gmail.com,zheng.cuizh@alibaba-inc.com]",'*',
|
50
|
+
"who will recevie the wish mail from you.",
|
51
|
+
"It coulde be String[one] or Array[multi].") {|vars[:receiver]|}
|
52
|
+
|
53
|
+
opts.on("-p", "--password=123456",
|
54
|
+
"if the smtp server's auth is required a password,you must give.") {|vars[:pw]|}
|
55
|
+
|
56
|
+
# separater
|
57
|
+
opts.on()
|
58
|
+
|
59
|
+
opts.on("--subject",
|
60
|
+
"the mail subject.") {|vars[:subject]|}
|
61
|
+
|
62
|
+
opts.on("--WMHeader=DearGirl") {|vars[:WMHeader]|}
|
63
|
+
|
64
|
+
opts.on("--WMBottom=Regards") {|vars[:WMBottom]|}
|
65
|
+
|
66
|
+
opts.on("--WMHeaderURI=http://docs.google.com/View?id=dcnwrnvv_886g2jzhqgd",String,
|
67
|
+
"Doesn't limitted using google doc.Any web page is OK.","It's very helpful.If this is given,--WMHeader=DearGirl will be ignored.") {|vars[:WMHeaderURI]|}
|
68
|
+
|
69
|
+
opts.on("--WMBottomURI=http://docs.google.com/View?id=dcnwrnvv_887cczt8vd7",String,
|
70
|
+
"Doesn't limitted using google doc.Any web page is OK.","It's very helpful.If this is given,--WMBottom=Regards will be ignored.") {|vars[:WMBottomURI]|}
|
71
|
+
|
72
|
+
vars[:log] = "~/wish_mailer.log"
|
73
|
+
opts.on("-l","--log=LogPath",
|
74
|
+
"default --log=#{vars[:log]}"){|vars[:log]|}
|
75
|
+
|
76
|
+
vars[:default_log_level] = 3
|
77
|
+
opts.on("--log_level=LogLevel",Integer,"1 => DEBUG","2 => INFO","3 => WARN","4 => ERROR","5 => FATAL",
|
78
|
+
"default --log_level=#{vars[:default_log_level]}"){|vars[:log_level]|}
|
79
|
+
|
80
|
+
# separater
|
81
|
+
opts.on_tail
|
82
|
+
opts.on_tail("common options:")
|
83
|
+
|
84
|
+
# no argument, shows at tail
|
85
|
+
opts.on_tail("--help", "show this message") {puts opts; exit}
|
86
|
+
|
87
|
+
# no argument
|
88
|
+
opts.on_tail("--version", "show version") do
|
89
|
+
puts "WishMailer : 0.11.25"
|
90
|
+
exit
|
91
|
+
end
|
92
|
+
opts.parse!
|
93
|
+
end
|
94
|
+
|
95
|
+
#----------------------------------Params Logic--------------------------------#
|
96
|
+
|
97
|
+
=begin
|
98
|
+
vars = {
|
99
|
+
:sender=>"i_sea@163.com",
|
100
|
+
:smtp=>"smtp.163.com",
|
101
|
+
:auto=>:login,
|
102
|
+
:receiver=>["zheng.cuizh@gmail.com","zheng.cuizh@alibaba-inc.com"],
|
103
|
+
:pw=>"123456789",
|
104
|
+
:subject=>"Morning Dear Jiao",
|
105
|
+
:log=>"./wish_mailer.log",
|
106
|
+
:log_level=>1,
|
107
|
+
:WMHeader=>"Hello My Dear",
|
108
|
+
:WMBottom=>"Regards.",
|
109
|
+
:WMHeaderURI=>"http://docs.google.com/View?id=dcnwrnvv_886g3jzxqgd",
|
110
|
+
:WMBottomURI=>"http://docs.google.com/View?id=dcnwrnve_88xgfjzeqmd"
|
111
|
+
}
|
112
|
+
=end
|
113
|
+
|
114
|
+
if vars[:wmyaml] then
|
115
|
+
begin
|
116
|
+
File.open(vars[:wmyaml]){|f|vars = YAML.load(f.read)}
|
117
|
+
rescue => e
|
118
|
+
Features.log.error "Can't Load YAML file." + $/ + e.to_s
|
119
|
+
exit(-2)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
if(vars[:WMHeaderURI])
|
124
|
+
$WMHeader = URI.parse(vars[:WMHeaderURI])
|
125
|
+
else
|
126
|
+
$WMHeader = vars[:WMHeader]
|
127
|
+
end
|
128
|
+
|
129
|
+
if(vars[:WMBottomURI])
|
130
|
+
$WMBottom = URI.parse(vars[:WMBottomURI])
|
131
|
+
else
|
132
|
+
$WMBottom = vars[:WMBottom]
|
133
|
+
end
|
134
|
+
|
135
|
+
#----------------------------------Logger Init--------------------------------#
|
136
|
+
|
137
|
+
logger = nil
|
138
|
+
|
139
|
+
begin
|
140
|
+
#Logger::Formatter::Format = "%s, [%s#%d] %5s -- %s: %s#{$/}"
|
141
|
+
logger = Logger.new(vars[:log],'daily',1048576)
|
142
|
+
if vars[:log_level] && (vars[:log_level] >= 1 || vars[:log_level] <= 5) then
|
143
|
+
logger.level = vars[:log_level]
|
144
|
+
else
|
145
|
+
logger.level = vars[:default_log_level]
|
146
|
+
end
|
147
|
+
rescue Exception => e
|
148
|
+
logger = nil
|
149
|
+
p "params error:#{e.to_s}"
|
150
|
+
p "can't access log file => #{vars[:log]}"
|
151
|
+
exit(-1)
|
152
|
+
end
|
153
|
+
|
154
|
+
logger.info "WishMailer is starting..."
|
155
|
+
logger.info "WishMailer parameters are below : #{vars.inspect}"
|
156
|
+
|
157
|
+
Features.log = logger
|
158
|
+
vars[:log] = logger
|
159
|
+
|
160
|
+
|
161
|
+
#----------------------------------Send Mail--------------------------------#
|
162
|
+
|
163
|
+
|
164
|
+
Dir[File.join(File.dirname(__FILE__),"..","lib","feature","*.rb")].each do |rb|
|
165
|
+
require rb
|
166
|
+
end
|
167
|
+
|
168
|
+
content = <<EOFMAIL
|
169
|
+
#{$WMHeader}
|
170
|
+
#{"<br/>"*4}
|
171
|
+
|
172
|
+
#{Features.pool.inject([]){|ct,obj|
|
173
|
+
begin
|
174
|
+
ct << obj.fdata
|
175
|
+
rescue Exception => ex
|
176
|
+
Features.log.error ex.to_s
|
177
|
+
end
|
178
|
+
}.join($/)
|
179
|
+
}
|
180
|
+
|
181
|
+
#{"<br/>"*4}
|
182
|
+
#{$WMBottom}
|
183
|
+
EOFMAIL
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
begin
|
188
|
+
wm = WishMailer.new(vars)
|
189
|
+
wm.send(content)
|
190
|
+
rescue => ex
|
191
|
+
Features.log.error ex.to_s
|
192
|
+
end
|
data/bin/wm.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
:smtp: smtp.163.com
|
3
|
+
:WMBottomURI: http://docs.google.com/View?id=dcnwrnve_88xgfjzeqmd
|
4
|
+
:log: ./wish_mail.log
|
5
|
+
:auto: :login
|
6
|
+
:pw: "123456"
|
7
|
+
:WMHeader: Hello My Dear
|
8
|
+
:log_level: 1
|
9
|
+
:subject: Morning Dear Jiao
|
10
|
+
:WMBottom: Regards.
|
11
|
+
:receiver:
|
12
|
+
- zheng.cuizh@gmail.com
|
13
|
+
- zheng.cuizh@alibaba-inc.com
|
14
|
+
:sender: i_sea@163.com
|
15
|
+
:WMHeaderURI: http://docs.google.com/View?id=dcnwrnvv_886g3jzxqgd
|
data/lib/WishMailer.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "activerecord"
|
3
|
+
require 'net/smtp'
|
4
|
+
require "net/http"
|
5
|
+
require "uri"
|
6
|
+
require "logger"
|
7
|
+
require "base64"
|
8
|
+
require "cgi"
|
9
|
+
|
10
|
+
require "open-uri"
|
11
|
+
require "iconv"
|
12
|
+
require 'hpricot'
|
13
|
+
|
14
|
+
class WishMailer
|
15
|
+
|
16
|
+
def initialize(opts={})
|
17
|
+
@log = opts[:log] || Logger.new('wish_mailer.log','weekly')
|
18
|
+
|
19
|
+
(@smtp = opts[:smtp]) || (raise ArgumentError,"WishMailer.new() => :smtp must be given")
|
20
|
+
|
21
|
+
raise ArgumentError,"WishMailer.new() => :receiver must be given" unless opts[:receiver]
|
22
|
+
case opts[:receiver]
|
23
|
+
when String
|
24
|
+
@receiver = [opts[:receiver]]
|
25
|
+
when Array
|
26
|
+
@receiver = opts[:receiver]
|
27
|
+
else
|
28
|
+
raise ArgumentError,"WishMailer.new() => :receiver must be string or array"
|
29
|
+
end
|
30
|
+
|
31
|
+
(@sender = opts[:sender]) || (raise ArgumentError,"WishMailer.new() => :sender must be given")
|
32
|
+
@sender_nick = opts[:sender_nick] || ""
|
33
|
+
@domain = opts[:domain] || @sender.split('@').pop
|
34
|
+
|
35
|
+
@subject = opts[:subject] || "Best Wish in this Mail."
|
36
|
+
# Base64.decode64("eWlqaXVzaGl3bw==\n")
|
37
|
+
@pw = opts[:pw] || ""
|
38
|
+
|
39
|
+
if [:plain,:login,:cram_md5,"plaint","login","cram_md5"].include?(opts[:auth]) then
|
40
|
+
@auth_mode = opts[:auth].to_sym
|
41
|
+
elsif @pw!=""
|
42
|
+
@auth_mode = :login
|
43
|
+
else
|
44
|
+
@auth_mode = :plain
|
45
|
+
end
|
46
|
+
|
47
|
+
@smtp_port = opts[:port] || 25
|
48
|
+
end
|
49
|
+
|
50
|
+
# Date: Sat, 23 Jun 2001 16:26:43 +0900
|
51
|
+
def get_content(content)
|
52
|
+
<<-EndOfMail
|
53
|
+
From: #{@sender_nick} <#{@sender}>
|
54
|
+
To: #{@receiver.map{|x|"<#{x}>"}.join(",")}
|
55
|
+
Subject: #{@subject}
|
56
|
+
Date: #{Time.now.ctime}
|
57
|
+
Message-Id: #{Time.now.to_i}
|
58
|
+
Content-Type: text/html
|
59
|
+
X-Mailer: Yours Charles(Cui)
|
60
|
+
|
61
|
+
<html>
|
62
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
63
|
+
<body>
|
64
|
+
#{content}
|
65
|
+
</body>
|
66
|
+
</html>
|
67
|
+
EndOfMail
|
68
|
+
end
|
69
|
+
|
70
|
+
def send(ct)
|
71
|
+
content = self.get_content(ct)
|
72
|
+
@log.info content
|
73
|
+
|
74
|
+
Net::SMTP.start( @smtp, @smtp_port , @domain, @sender , @pw , @auth_mode) {|smtp|
|
75
|
+
smtp.open_timeout = 120
|
76
|
+
smtp.read_timeout = 120
|
77
|
+
begin
|
78
|
+
smtp.send_mail content , @sender , *@receiver
|
79
|
+
rescue Exception => e
|
80
|
+
err_msg = []
|
81
|
+
err_msg << Time.now.to_s
|
82
|
+
err_msg << "DANGEROUS : This Wish Mail Couldn't Be Sent!"
|
83
|
+
err_msg << e.to_s
|
84
|
+
|
85
|
+
smtp.send_mail err_msg , @sender
|
86
|
+
@log.fatal err_msg.join($/)
|
87
|
+
end
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
module Features
|
94
|
+
@pool = []
|
95
|
+
@log = Logger.new(File.join(File.dirname(__FILE__),'..','log','wish_mailer.log'),'weekly',1024000)
|
96
|
+
|
97
|
+
class << self
|
98
|
+
attr :pool,true
|
99
|
+
attr :log,true
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.included(receiver)
|
103
|
+
@pool << (receiver.send :new)
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
begin
|
2
|
+
Features.log.info __FILE__.center(100,'*')
|
3
|
+
|
4
|
+
# raise RuntimeError,"Google doc is not regular text,the html code make Iconv.conv error."
|
5
|
+
|
6
|
+
if($WMHeader.class.to_s =~ /URI/)
|
7
|
+
# $WMHeader => "http://docs.google.com/View?id=dcnwrnvv_886g2jzhqgd"
|
8
|
+
$WMHeader = Hpricot(Iconv.conv('utf-8','utf-8', open($WMHeader).readlines.join($/))).search("div[@id=doc-contents]").inner_html
|
9
|
+
Features.log.info "Get header from google doc => #{$WMHeader}"
|
10
|
+
end
|
11
|
+
|
12
|
+
if($WMBottom.class.to_s =~ /URI/)
|
13
|
+
# $WMBottom => "http://docs.google.com/View?id=dcnwrnvv_887cczt8vd7"
|
14
|
+
$WMBottom = Hpricot(Iconv.conv('utf-8','utf-8', open($WMBottom).readlines.join($/))).search("div[@id=doc-contents]").inner_html
|
15
|
+
Features.log.info "Get bottom from google doc => #{$WMBottom}"
|
16
|
+
end
|
17
|
+
rescue => e
|
18
|
+
Features.log.info __FILE__
|
19
|
+
Features.log.error e.to_s
|
20
|
+
|
21
|
+
if($WMHeader.class.to_s =~ /URI/)
|
22
|
+
$WMHeader = <<HEADER
|
23
|
+
My Friend,
|
24
|
+
#{"<br/>"*2}
|
25
|
+
这是为你定制的一封邮件,如这世界还有电,那它至少能发一万年!
|
26
|
+
#{"<br/>"*2}
|
27
|
+
HEADER
|
28
|
+
end
|
29
|
+
|
30
|
+
if($WMBottom.class.to_s =~ /URI/)
|
31
|
+
$WMBottom = <<BOTTOM
|
32
|
+
你要健康,你要快乐!如果不是,请告诉我^-^
|
33
|
+
#{"<br/>"*2}
|
34
|
+
BOTTOM
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
class GoogleMovie
|
3
|
+
def initialize(opts = {:cs => [],:logger => Logger.new(File.join(File.dirname(__FILE__),'..','..','log','wish_mailer.log'))})
|
4
|
+
require "open-uri"
|
5
|
+
require "iconv"
|
6
|
+
require 'hpricot'
|
7
|
+
|
8
|
+
@log = opts[:logger] || Logger.new(File.join(File.dirname(__FILE__),'..','..','log','wish_mailer.log'))
|
9
|
+
@movies = {}
|
10
|
+
@base_url = opts[:url] || "http://www.google.cn/movies?hl=zh-CN&sort=1&sa=X&oi=showtimes&ct=title&cd=1&near="
|
11
|
+
|
12
|
+
begin
|
13
|
+
@log.info "Get Google Movie data..."
|
14
|
+
case opts[:cs]
|
15
|
+
when Array
|
16
|
+
opts[:cs].each{|c| @movies[c] = {:uri => URI.parse(@base_url+c),:doc => Hpricot(open(@base_url+c).readlines.join($/))}}
|
17
|
+
when String
|
18
|
+
@movies[opts[:cs]] = {:uri => URI.parse(@base_url+opts[:cs]),:doc => Hpricot(open(@base_url+opts[:cs]).readlines.join($/))}
|
19
|
+
else
|
20
|
+
raise ArgumentError,"City(s) not available => #{opts[:cs]}."
|
21
|
+
end
|
22
|
+
@log.info "Movies => " + $/ + @movies.inspect
|
23
|
+
rescue Exception => e
|
24
|
+
@log.error e.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def fdata(d="")
|
30
|
+
r = []
|
31
|
+
r << "Recent Movies"
|
32
|
+
r << "<br/>"*2
|
33
|
+
|
34
|
+
return nil if @movies.size <= 0
|
35
|
+
|
36
|
+
@movies.each do |c,obj|
|
37
|
+
r << "@" + c + "<br/>"*2
|
38
|
+
# @log.info "*"*50 + $/ + obj[:doc] + $/ + "*"*50
|
39
|
+
obj[:doc].search("div[@class=movie]").each do |div|
|
40
|
+
content = div.inner_html.gsub("href=\"","href=\"http://www.google.cn").gsub("src=\"","src=\"http://www.google.cn")
|
41
|
+
r << Hpricot(Iconv.conv('utf-8','GBK', content))
|
42
|
+
end
|
43
|
+
# content = obj[:doc].search("div[@class=movie]")[1].inner_html.gsub("href=\"","href=\"http://www.google.cn").gsub("src=\"","src=\"http://www.google.cn")
|
44
|
+
# r << Hpricot(Iconv.conv('utf-8','GBK', content))
|
45
|
+
end
|
46
|
+
|
47
|
+
r.join(d) + "<br/>"*4
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
Features.pool << GoogleMovie.new(:cs=>['BeiJing'],:log=>Features.log)
|
@@ -0,0 +1,102 @@
|
|
1
|
+
class GoogleWeather
|
2
|
+
attr :citys
|
3
|
+
|
4
|
+
def initialize(opts = {:cs => [],:log => Logger.new(File.join(File.dirname(__FILE__),'..','..','log','wish_mailer.log'))})
|
5
|
+
# HangZhou
|
6
|
+
# http://www.google.com/ig/api?hl=cn&weather=HangZhou
|
7
|
+
# BeiJing
|
8
|
+
# http://www.google.com/ig/api?hl=cn&weather=BeiJing
|
9
|
+
@base_url = "http://www.google.com/ig/api?hl=cn&weather="
|
10
|
+
@log = opts[:log] || Logger.new(File.join(File.dirname(__FILE__),'..','..','log','wish_mailer.log'))
|
11
|
+
|
12
|
+
@citys = {}
|
13
|
+
@log.info "Citys =>#{opts[:cs].inspect}"
|
14
|
+
|
15
|
+
begin
|
16
|
+
case opts[:cs]
|
17
|
+
when Array
|
18
|
+
opts[:cs].each{|c|@citys[c] = {:uri => URI.parse(@base_url+CGI.escape(c))}}
|
19
|
+
when String
|
20
|
+
@citys[opts[:cs]] = {:uri => URI.parse{@base_url+CGI.escape(cs)}}
|
21
|
+
else
|
22
|
+
raise ArgumentError,"Weather.new(citys) #citys couldn't nil,String or Array is ok."
|
23
|
+
end
|
24
|
+
rescue => e
|
25
|
+
@log.error e.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
@log.info @citys.inspect
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_weather
|
32
|
+
@citys.each do |city,hobj|
|
33
|
+
@log.debug "City=>#{city},URI=>#{hobj[:uri]}"
|
34
|
+
begin
|
35
|
+
Net::HTTP.start(hobj[:uri].host, hobj[:uri].port) {|http|
|
36
|
+
response = http.get(hobj[:uri].request_uri)
|
37
|
+
@log.info "Get Weather #{city} from Google...Patient"
|
38
|
+
@log.info response.body
|
39
|
+
@citys[city][:data] = Hash.from_xml(response.body)
|
40
|
+
}
|
41
|
+
rescue => e
|
42
|
+
@log.error e.to_s
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
@citys
|
47
|
+
end
|
48
|
+
|
49
|
+
def fdata
|
50
|
+
report = []
|
51
|
+
report << "Weather"
|
52
|
+
report << "<br/>"*2
|
53
|
+
|
54
|
+
report << "<table border='1'>"
|
55
|
+
|
56
|
+
def format_table(* args)
|
57
|
+
# args[0].to_s.center(15,'*') + '|' + args[1].to_s.center(20,'*') + '|' + args[2].to_s.center(10,'*') + '|' + args[3].to_s.center(10,'*') + '|' + args[4].to_s.center(15,'*')
|
58
|
+
"<tr align='center'>" + args.inject(""){|result,x|result += "<td>#{x}</td>"} + "</tr>"
|
59
|
+
end
|
60
|
+
|
61
|
+
def icon_cell(src)
|
62
|
+
"<img src=#{src}/>"
|
63
|
+
end
|
64
|
+
|
65
|
+
# header = format_table "City","day_of_week","Low","High","Condition"
|
66
|
+
header = format_table("City","day_of_week","Low(℃)","High(℃)","Condition","")
|
67
|
+
report << header
|
68
|
+
|
69
|
+
try_time = 1
|
70
|
+
|
71
|
+
begin
|
72
|
+
@citys.each do |ct,obj|
|
73
|
+
obj[:data]["xml_api_reply"]["weather"]["forecast_conditions"].each do |fc|
|
74
|
+
report << format_table(ct,fc["day_of_week"]["data"],fc["low"]["data"].to_f.f2c.to_s[0..4],fc["high"]["data"].to_f.f2c.to_s[0..4],fc["condition"]["data"],icon_cell("'#{obj[:uri].scheme + "://" + obj[:uri].host + fc["icon"]["data"]}'"))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
@log.info report.inspect
|
78
|
+
rescue NoMethodError => e
|
79
|
+
@log.error e.to_s
|
80
|
+
@log.info "Try #{try_time}(times)."
|
81
|
+
self.get_weather
|
82
|
+
(try_time+=1; retry) if(try_time <= 3)
|
83
|
+
end
|
84
|
+
|
85
|
+
report << "</table>"
|
86
|
+
(report.join $/) + "<br/>"*4
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
class Numeric
|
92
|
+
def f2c
|
93
|
+
# 华氏℉(Fahrenheit)=℃×9/5+32.摄氏℃(Celsius or Centigrade)=5/9×(℉-32)
|
94
|
+
5.0/9*(self.to_f-32)
|
95
|
+
end
|
96
|
+
|
97
|
+
def c2f
|
98
|
+
self.to_f*9.0/5+32
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
Features.pool << GoogleWeather.new(:cs=>['BeiJing','HangZhou'],:log=>Features.log)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
class TodayInHistory
|
3
|
+
|
4
|
+
def initialize(opts = {:url => "http://www1.wst.net.cn/scripts/flex/TodayOnHistory/",:log => Logger.new(File.join(File.dirname(__FILE__),'..','..','log','wish_mailer.log'))})
|
5
|
+
require "open-uri"
|
6
|
+
require "iconv"
|
7
|
+
require 'hpricot'
|
8
|
+
|
9
|
+
@log = opts[:log] || Logger.new(File.join(File.dirname(__FILE__),'..','..','log','wish_mailer.log'))
|
10
|
+
|
11
|
+
begin
|
12
|
+
@log.info "Get TodayInHistroy...Patient"
|
13
|
+
page = open(opts[:url])
|
14
|
+
content = page.readlines.join($/)
|
15
|
+
|
16
|
+
@doc = Hpricot(Iconv.conv('utf-8','GBK', content))
|
17
|
+
# @doc = Hpricot(page)
|
18
|
+
rescue => e
|
19
|
+
@log.error e.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def fdata
|
25
|
+
begin
|
26
|
+
r = []
|
27
|
+
r << "Today In Histroy"
|
28
|
+
r << "<br/>"*2
|
29
|
+
r << "<ol>"
|
30
|
+
|
31
|
+
# :url => "http://www.todayonhistory.com/"
|
32
|
+
# (@doc/'//div[@id=d4]/li').search("a").each{|x| r << x.inner_text}
|
33
|
+
# A faster page:
|
34
|
+
# :url => "http://www1.wst.net.cn/scripts/flex/TodayOnHistory/"
|
35
|
+
(@doc/'//td[@class=a]').search("a").each{|x| r << "<li>#{x.inner_text}</li>"}
|
36
|
+
|
37
|
+
r << "</ol>"
|
38
|
+
r.join($/) + "<br/>"*4
|
39
|
+
rescue => e
|
40
|
+
@log.error e.to_s
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# => Such as this class
|
46
|
+
# the initialize function doeesn't need any more params
|
47
|
+
# so we just include the Features module
|
48
|
+
# and this class's instance will be automatically added to Features.pool
|
49
|
+
# this code's value is equal to "Features.pool << TodayInHistory.new"
|
50
|
+
# and this code must write at the bottom of the class.
|
51
|
+
include Features
|
52
|
+
end
|
53
|
+
|
54
|
+
#Features.pool << TodayInHistory.new
|
data/lib/main.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'WishMailer.rb')
|
2
|
+
|
3
|
+
$WMHeader = nil
|
4
|
+
$WMBottom = nil
|
5
|
+
|
6
|
+
Dir[File.join(File.dirname(__FILE__),"feature","*.rb")].each do |rb|
|
7
|
+
require rb
|
8
|
+
end
|
9
|
+
|
10
|
+
content = <<EOFMAIL
|
11
|
+
#{$WMHeader}
|
12
|
+
#{"<br/>"*1}
|
13
|
+
|
14
|
+
#{c = Features.pool.inject([]){|ct,obj|
|
15
|
+
begin
|
16
|
+
ct << obj.fdata
|
17
|
+
rescue Exception => ex
|
18
|
+
Features.log.error ex.to_s
|
19
|
+
end
|
20
|
+
}
|
21
|
+
c.join($/)
|
22
|
+
}
|
23
|
+
|
24
|
+
#{"<br/>"*4}
|
25
|
+
#{$WMBottom}
|
26
|
+
EOFMAIL
|
27
|
+
|
28
|
+
wm_params = {
|
29
|
+
:sender=>"i_sea@163.com",
|
30
|
+
:smtp=>"smtp.163.com",
|
31
|
+
:receiver=>["zheng.cuizh@gmail.com","zheng.cuizh@alibaba-inc.com"],
|
32
|
+
:pw=>Base64.decode64("eWlqaXVzaGl3bw==\n"),
|
33
|
+
:subject=>"Morning Dear Jiao",
|
34
|
+
:log=>Features.log
|
35
|
+
}
|
36
|
+
|
37
|
+
begin
|
38
|
+
wm = WishMailer.new(wm_params)
|
39
|
+
wm.send(content)
|
40
|
+
rescue => ex
|
41
|
+
Features.log.error ex.to_s
|
42
|
+
end
|
data/log/wish_mailer.log
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: WIshMailer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.11.25
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- CharlesCui
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-07 00:00:00 +08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Wish from heart,to best friend.
|
17
|
+
email: zheng.cuizh@gmail.com
|
18
|
+
executables:
|
19
|
+
- wishmailer
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- LICENSE
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README
|
28
|
+
- Rakefile
|
29
|
+
- bin/wishmailer
|
30
|
+
- bin/wm.yaml
|
31
|
+
- lib/feature/ContentControl.rb
|
32
|
+
- lib/feature/GoogleMovie.rb
|
33
|
+
- lib/feature/GoogleWeather.rb
|
34
|
+
- lib/feature/TodayInHistory.rb
|
35
|
+
- lib/main.rb
|
36
|
+
- lib/WishMailer.rb
|
37
|
+
- log/wish_mailer.log
|
38
|
+
has_rdoc: true
|
39
|
+
homepage:
|
40
|
+
licenses: []
|
41
|
+
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.3.5
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Wish from heart,to best friend.
|
66
|
+
test_files: []
|
67
|
+
|