WIshMailer 0.11.25
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/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
|
+
|