typedown2blog 0.0.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/README.rdoc +11 -23
- data/Rakefile +3 -2
- data/VERSION +1 -1
- data/example/bin/blog.rb +30 -0
- data/example/bin/mail2test.rb +31 -0
- data/example/bin/pop2blog.rb +79 -0
- data/example/config/config.template.yaml +27 -0
- data/example/script/db_init.rb +52 -0
- data/example/test/data/example.tpd +21 -0
- data/lib/typedown2blog/base.rb +43 -0
- data/lib/typedown2blog/blog_post.rb +112 -0
- data/lib/typedown2blog/formatters.rb +37 -0
- data/lib/typedown2blog/instance_exec.rb +17 -0
- data/lib/typedown2blog/spec.rb +31 -9
- data/lib/typedown2blog.rb +4 -3
- data/test/data/example.tpd +21 -0
- data/test/test_blog_post.rb +43 -0
- data/test/test_typedown2blog.rb +37 -9
- metadata +42 -20
- data/bin/blog +0 -27
- data/bin/control_typedown2blog_batcher.rb +0 -6
- data/bin/typedown2blog_batcher +0 -40
- data/lib/typedown2blog/blog.rb +0 -41
- data/lib/typedown2blog/parse_mail.rb +0 -74
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -10,31 +10,19 @@ emails once processed. If you don't want this behaviour you can easily create
|
|
10
10
|
your own version of the script. You have to move the mail out of the
|
11
11
|
watched directory though, or the mail will be reprocessed every 3 seconds.
|
12
12
|
|
13
|
+
== NEW STUFF
|
14
|
+
|
15
|
+
0.1.0
|
16
|
+
|
17
|
+
* Major refactoring of the whole library.
|
18
|
+
|
13
19
|
== USAGE
|
14
20
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
blog do
|
21
|
-
email 'blog@example.com'
|
22
|
-
end
|
23
|
-
|
24
|
-
mail_defaults do
|
25
|
-
delivery_method :smtp, {
|
26
|
-
:address => 'your_mail_server',
|
27
|
-
:port => 25,
|
28
|
-
:domain => 'example.com',
|
29
|
-
:user_name => 'you@example.com',
|
30
|
-
:password => 'your_password',
|
31
|
-
:authentication => :plain,
|
32
|
-
}
|
33
|
-
end
|
34
|
-
|
35
|
-
# Only used by bin/typedown2blog_batcher
|
36
|
-
glob "your_home/Maildir/new/*"
|
37
|
-
end
|
21
|
+
Check out the example dir. You may copy this directory to
|
22
|
+
start your own project. Remember to create your own
|
23
|
+
config/config.yaml from config/config.template.yaml
|
24
|
+
|
25
|
+
example/bin/pop2blog.rb depends on the 'secret_mail' gem
|
38
26
|
|
39
27
|
|
40
28
|
== Note on Patches/Pull Requests
|
data/Rakefile
CHANGED
@@ -11,8 +11,9 @@ begin
|
|
11
11
|
gem.homepage = "http://github.com/wrimle/typedown2blog"
|
12
12
|
gem.authors = ["Rune Myrland"]
|
13
13
|
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
14
|
-
gem.add_dependency('attachments','>= 0.0.
|
15
|
-
gem.add_dependency('typedown','>= 0.0.
|
14
|
+
gem.add_dependency('attachments','>= 0.0.11')
|
15
|
+
gem.add_dependency('typedown','>= 0.0.5')
|
16
|
+
gem.add_dependency('mail_processor','>= 0.0.2')
|
16
17
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
18
|
end
|
18
19
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.1
|
data/example/bin/blog.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'rubygems'
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
+
require 'typedown2blog'
|
8
|
+
|
9
|
+
include Typedown2Blog
|
10
|
+
|
11
|
+
|
12
|
+
config = YAML::load(File.open("config/config.yaml"))
|
13
|
+
|
14
|
+
Typedown2Blog::Spec::setup do
|
15
|
+
retriever_method :pop3, config["pop3"]
|
16
|
+
delivery_method :smtp, config["smtp"]
|
17
|
+
end
|
18
|
+
|
19
|
+
post = BlogPost.new config["blog_post"]
|
20
|
+
|
21
|
+
isFirst = true
|
22
|
+
ARGV.each do |filename|
|
23
|
+
if isFirst
|
24
|
+
post.typedown_body = File.read(filename)
|
25
|
+
isFirst = false
|
26
|
+
else
|
27
|
+
post.add_attachment filename
|
28
|
+
end
|
29
|
+
end
|
30
|
+
post.post!
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'rubygems'
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
+
require 'typedown2blog'
|
8
|
+
|
9
|
+
include Typedown2Blog
|
10
|
+
|
11
|
+
|
12
|
+
config = YAML::load(File.open("config/config.yaml"))
|
13
|
+
Typedown2Blog::Spec::setup do
|
14
|
+
delivery_method :smtp, config["smtp"]
|
15
|
+
end
|
16
|
+
|
17
|
+
mail = Mail.new do
|
18
|
+
to config["test"]["secret_mail"]
|
19
|
+
from config["test"]["mail_from"]
|
20
|
+
end
|
21
|
+
|
22
|
+
isFirst = true
|
23
|
+
ARGV.each do |filename|
|
24
|
+
if isFirst
|
25
|
+
mail.body File.read(filename)
|
26
|
+
isFirst = false
|
27
|
+
else
|
28
|
+
mail.add_file filename
|
29
|
+
end
|
30
|
+
end
|
31
|
+
mail.deliver!
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
# from 'mail' gem
|
5
|
+
require 'mail'
|
6
|
+
# from 'secret_mail' gem
|
7
|
+
require 'secret_mail'
|
8
|
+
# from 'uuidtools' gem
|
9
|
+
require 'uuidtools'
|
10
|
+
# from 'log4r' gem
|
11
|
+
require 'log4r'
|
12
|
+
require 'log4r/outputter/syslogoutputter'
|
13
|
+
|
14
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '../..', 'lib'))
|
15
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
16
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
17
|
+
require 'typedown2blog'
|
18
|
+
|
19
|
+
include Log4r
|
20
|
+
|
21
|
+
log = Log4r::Logger.new("pop2blog")
|
22
|
+
outputter = Outputter.stdout
|
23
|
+
#outputter = Log4r::FileOutputter.new "pop2blog", { :filename => "pop2blog.log" }
|
24
|
+
#outputter = Log4r::SyslogOutputter.new "pop2blog"
|
25
|
+
Log4r::Logger[ "pop2blog" ].outputters = outputter
|
26
|
+
Log4r::Logger[ "Typedown2Blog" ].outputters = outputter
|
27
|
+
Log4r::Logger[ "MailProcessor" ].outputters = outputter
|
28
|
+
|
29
|
+
config = YAML::load(File.open("config/config.yaml"))
|
30
|
+
|
31
|
+
Typedown2Blog::Spec::setup do
|
32
|
+
retriever_method :pop3, config["pop3"]
|
33
|
+
delivery_method :smtp, config["smtp"]
|
34
|
+
end
|
35
|
+
|
36
|
+
SecretMail::MailAction.mail_domain config["secret_mail"]["mail_domain"]
|
37
|
+
ActiveRecord::Base.establish_connection(config["db"])
|
38
|
+
|
39
|
+
|
40
|
+
loop do
|
41
|
+
didWork = Spec::retriever.process do |popped|
|
42
|
+
begin
|
43
|
+
SecretMail::Controller.process Mail.new(popped) do |action, record, mail|
|
44
|
+
blog_post = Typedown2Blog::BlogPost.new do
|
45
|
+
case action.to_sym
|
46
|
+
when :created then
|
47
|
+
self.mail_to = mail.from[0]
|
48
|
+
self.mail_from = record.secret_mail
|
49
|
+
self.typedown_body = "! Your typedown2blog gateway\n#{record.secret_mail}\n"
|
50
|
+
self.format = 'blogger'
|
51
|
+
when :mail_to_blogger then
|
52
|
+
self.mail_to = record.params
|
53
|
+
self.format = 'blogger'
|
54
|
+
self.import_mail :mail => mail
|
55
|
+
when :mail_to_wordpress then
|
56
|
+
self.mail_to = record.params
|
57
|
+
self.format = 'wordpress'
|
58
|
+
self.import_mail :mail => mail
|
59
|
+
else
|
60
|
+
raise "Unsupported action: " + action.to_s
|
61
|
+
end
|
62
|
+
end
|
63
|
+
blog_post.post!
|
64
|
+
end
|
65
|
+
rescue => err
|
66
|
+
now = Time.now.strftime("%Y%m%d-%H%M%S")
|
67
|
+
uuid = UUIDTools::UUID.random_create.to_s
|
68
|
+
filename = "failed/#{now}-#{uuid}"
|
69
|
+
log.error filename + ", " + err.message
|
70
|
+
f = File.new(filename, "wb")
|
71
|
+
f.write(popped)
|
72
|
+
f.close()
|
73
|
+
f = File.new(filename + ".error", "wb")
|
74
|
+
f.write("#{err.message}\n#{err.backtrace.join("\n")}")
|
75
|
+
f.close()
|
76
|
+
end
|
77
|
+
end
|
78
|
+
sleep(10) unless(didWork)
|
79
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Used by both
|
2
|
+
smtp:
|
3
|
+
address: smtp.your_provider.example.com
|
4
|
+
port: 25
|
5
|
+
|
6
|
+
# Used only by pop2blog.rb
|
7
|
+
pop3:
|
8
|
+
address: pop.your_provider.example.com
|
9
|
+
username: your_pop_user_name
|
10
|
+
password: **secret**
|
11
|
+
|
12
|
+
db:
|
13
|
+
adapter: sqlite3
|
14
|
+
database: db/production.sqlite3
|
15
|
+
|
16
|
+
secret_mail:
|
17
|
+
mail_domain: your_domain.example.com
|
18
|
+
|
19
|
+
test:
|
20
|
+
secret_mail: your_test_account@server.example.com
|
21
|
+
mail_to: your_test_blog_or_personal_mail@some_blog.example.com
|
22
|
+
mail_from: you@example.com
|
23
|
+
|
24
|
+
# Used only by blog.rb
|
25
|
+
blog_post:
|
26
|
+
mail_to: your@server.example.com
|
27
|
+
mail_from: you@example.com
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'secret_mail'
|
5
|
+
require 'secret_mail/../../db/create_tables'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
config = YAML::load(File.open("config/config.yaml"))
|
9
|
+
|
10
|
+
db_file = config["db"]["database"]
|
11
|
+
file_exist = false
|
12
|
+
if File.exists?(db_file)
|
13
|
+
puts "Db already exists"
|
14
|
+
file_exist = true
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
|
18
|
+
SecretMail::MailAction.mail_domain config["secret_mail"]["mail_domain"]
|
19
|
+
ActiveRecord::Base.establish_connection(config["db"])
|
20
|
+
ActiveRecord::Base.connection
|
21
|
+
|
22
|
+
CreateTables.up
|
23
|
+
domain = SecretMail::MailAction.mail_domain
|
24
|
+
|
25
|
+
|
26
|
+
SecretMail::MailAction.new({
|
27
|
+
:secret_mail => "blogger@#{domain}",
|
28
|
+
:action => "create",
|
29
|
+
:params => "mail_to_blogger"
|
30
|
+
}).save
|
31
|
+
|
32
|
+
|
33
|
+
SecretMail::MailAction.new({
|
34
|
+
:secret_mail => "wordpress@#{domain}",
|
35
|
+
:action => "create",
|
36
|
+
:params => "mail_to_wordpress"
|
37
|
+
}).save
|
38
|
+
|
39
|
+
|
40
|
+
SecretMail::MailAction.new({
|
41
|
+
:secret_mail => "posterous@#{domain}",
|
42
|
+
:action => "create",
|
43
|
+
:params => "mail_to_wordpress"
|
44
|
+
}).save
|
45
|
+
|
46
|
+
|
47
|
+
SecretMail::MailAction.new({
|
48
|
+
:secret_mail => config["test"]["secret_mail"],
|
49
|
+
:action => "mail_to_wordpress",
|
50
|
+
:from => config["test"]["mail_from"],
|
51
|
+
:params => config["test"]["mail_to"]
|
52
|
+
}).save
|
@@ -0,0 +1,21 @@
|
|
1
|
+
! Heading
|
2
|
+
|
3
|
+
//. A lead-in saying what the article is about.
|
4
|
+
Some more lead-in.
|
5
|
+
And more.
|
6
|
+
|
7
|
+
Some body copy.
|
8
|
+
|
9
|
+
!! Subheading
|
10
|
+
|
11
|
+
More body copy.
|
12
|
+
|
13
|
+
- Dialogue like this, he said. - I tell you.
|
14
|
+
|
15
|
+
- Oh, yeah?
|
16
|
+
|
17
|
+
More body copy. Standard markdown /italic/ and //bold//.
|
18
|
+
|
19
|
+
!! Another subheading
|
20
|
+
|
21
|
+
And body copy again.
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'log4r'
|
5
|
+
|
6
|
+
module Typedown2Blog
|
7
|
+
include Log4r
|
8
|
+
class UnkownRetrieverError < StandardError; end
|
9
|
+
|
10
|
+
log = Log4r::Logger.new "Typedown2Blog"
|
11
|
+
log.outputters = Log4r::Outputter.stdout
|
12
|
+
|
13
|
+
class Base
|
14
|
+
def self.log
|
15
|
+
Log4r::Logger["Typedown2Blog"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def log
|
19
|
+
self.class.log
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# Symbolizes keys from yaml hashes while merging
|
24
|
+
def merge_to_attributes other
|
25
|
+
h = @attributes
|
26
|
+
other.each do |k, v|
|
27
|
+
h[k.to_sym] = v
|
28
|
+
end
|
29
|
+
self
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
class File
|
36
|
+
def self.read_binary filename
|
37
|
+
f = File.new(filename, "rb")
|
38
|
+
content = f.read()
|
39
|
+
f.close()
|
40
|
+
content
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'attachments'
|
4
|
+
require 'typedown'
|
5
|
+
|
6
|
+
include Typedown2Blog
|
7
|
+
module Typedown2Blog
|
8
|
+
|
9
|
+
class BlogPost < Base
|
10
|
+
attr_accessor :mail_from, :mail_to, :typedown_body, :format
|
11
|
+
|
12
|
+
begin
|
13
|
+
@formatters = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def initialize options = {}, &block
|
18
|
+
@mail_to = nil
|
19
|
+
@mail_from = nil
|
20
|
+
@typedown_body = ""
|
21
|
+
@format = nil
|
22
|
+
@attachments = []
|
23
|
+
|
24
|
+
options.each do |k, v|
|
25
|
+
send("#{k}=", v)
|
26
|
+
end
|
27
|
+
|
28
|
+
instance_eval &block if block_given?
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.add_formatter name, formatter
|
32
|
+
@formatters[ name ] = formatter
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def self.formatters
|
37
|
+
@formatters
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_attachment options = {}
|
41
|
+
options[:content] = File.read_binary(options[:tmpfile]) unless options[:content]
|
42
|
+
@attachments << options
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def post!
|
47
|
+
mail_to = self.mail_to
|
48
|
+
mail_from = self.mail_from
|
49
|
+
mail_subject, mail_body, mail_content_type = self.format_body(self.typedown_body)
|
50
|
+
|
51
|
+
mail_attachments = @attachments
|
52
|
+
|
53
|
+
mail = Mail.new do
|
54
|
+
from mail_from
|
55
|
+
to mail_to
|
56
|
+
subject mail_subject
|
57
|
+
|
58
|
+
if mail_attachments.length == 0
|
59
|
+
body mail_body
|
60
|
+
content_type mail_content_type
|
61
|
+
else
|
62
|
+
text_part do
|
63
|
+
self.charset = "UTF-8"
|
64
|
+
body mail_body
|
65
|
+
content_type mail_content_type
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
mail_attachments.each do |a|
|
70
|
+
add_file(:filename => a[:save_as], :content => a[:content])
|
71
|
+
attachments[a[:save_as]][:content_type] = a[:mime_type]
|
72
|
+
end
|
73
|
+
|
74
|
+
#text_part.body mail_body
|
75
|
+
#text_part.content_type mail_content_type
|
76
|
+
end
|
77
|
+
|
78
|
+
log.info((mail_subject || "(No subject)") + " delivered to " + (mail_to || "(nobody)"))
|
79
|
+
mail.deliver!
|
80
|
+
end
|
81
|
+
|
82
|
+
def import_mail filename_or_hash
|
83
|
+
post = nil
|
84
|
+
extract = Attachments::Extract.new [ "image/jpeg" ]
|
85
|
+
begin
|
86
|
+
extract.parse filename_or_hash
|
87
|
+
self.mail_from = extract.from
|
88
|
+
|
89
|
+
typedown_root = Typedown::Section.sectionize(extract.text_body, extract.subject)
|
90
|
+
self.typedown_body = typedown_root.doc
|
91
|
+
|
92
|
+
extract.files.each do |f|
|
93
|
+
self.add_attachment f
|
94
|
+
end
|
95
|
+
ensure
|
96
|
+
extract.close
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
protected
|
101
|
+
def format_body typedown
|
102
|
+
if(format)
|
103
|
+
self.class.formatters[format].format_body typedown
|
104
|
+
else
|
105
|
+
doc = Typedown::Section.sectionize(typedown)
|
106
|
+
body = "#{doc.body.to_html}\n\n"
|
107
|
+
[ doc.title, body, "plain/text" ]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module Typedown2Blog
|
3
|
+
class BlogFormatter
|
4
|
+
def initialize name = nil
|
5
|
+
BlogPost.add_formatter(name || self.class.to_s, self)
|
6
|
+
end
|
7
|
+
|
8
|
+
def format_body typedown
|
9
|
+
raise "Pleas subclass and override this method."
|
10
|
+
[ "Subject", "Body", "mime/type" ]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
class HtmlTagsInText < BlogFormatter
|
16
|
+
def format_body typedown
|
17
|
+
doc = Typedown::Section.sectionize(typedown)
|
18
|
+
body = "#{doc.body.to_html}\n\n"
|
19
|
+
[ doc.title, body, "plain/text" ]
|
20
|
+
end
|
21
|
+
|
22
|
+
new "wordpress"
|
23
|
+
new "posterous"
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
class HtmlDocument < BlogFormatter
|
28
|
+
def format_body typedown
|
29
|
+
doc = Typedown::Section.sectionize(typedown)
|
30
|
+
body = "<html>\n<body>\n#{doc.body.to_html}\n</body>\n</html>\n\n"
|
31
|
+
[ doc.title, body, "plain/text" ]
|
32
|
+
end
|
33
|
+
|
34
|
+
new "blogger"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
class Object
|
4
|
+
module InstanceExecHelper; end
|
5
|
+
include InstanceExecHelper
|
6
|
+
def instance_exec(*args, &block) # !> method redefined; discarding old instance_exec
|
7
|
+
mname = "__instance_exec_#{Thread.current.object_id.abs}_#{object_id.abs}"
|
8
|
+
InstanceExecHelper.module_eval{ define_method(mname, &block) }
|
9
|
+
begin
|
10
|
+
ret = send(mname, *args)
|
11
|
+
ensure
|
12
|
+
InstanceExecHelper.module_eval{ undef_method(mname) } rescue nil
|
13
|
+
end
|
14
|
+
ret
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
data/lib/typedown2blog/spec.rb
CHANGED
@@ -1,27 +1,50 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
+
require 'mail_processor'
|
3
4
|
|
4
5
|
module Typedown2Blog
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def symbolize_keys(hash)
|
7
|
+
hash.inject({}){|result, (key, value)|
|
8
|
+
new_key = case key
|
9
|
+
when String then key.to_sym
|
10
|
+
else key
|
11
|
+
end
|
12
|
+
new_value = case value
|
13
|
+
when Hash then symbolize_keys(value)
|
14
|
+
else value
|
15
|
+
end
|
16
|
+
result[new_key] = new_value
|
17
|
+
result
|
18
|
+
}
|
19
|
+
end
|
9
20
|
|
10
21
|
|
22
|
+
class Spec
|
11
23
|
def self.setup &block
|
12
|
-
instance_eval &block
|
24
|
+
instance_eval &block if block_given?
|
25
|
+
self
|
13
26
|
end
|
14
27
|
|
15
|
-
|
16
|
-
|
17
|
-
|
28
|
+
def self.retriever_method method, options={}, &block
|
29
|
+
@retriever = MailProcessor::Processor.new do
|
30
|
+
retriever method, symbolize_keys(options), &block
|
31
|
+
end
|
32
|
+
@retriever
|
18
33
|
end
|
19
34
|
|
35
|
+
def self.retriever
|
36
|
+
@retriever
|
37
|
+
end
|
20
38
|
|
21
39
|
def self.mail_defaults &block
|
22
40
|
Mail.defaults &block
|
23
41
|
end
|
24
42
|
|
43
|
+
def self.delivery_method m, options= {}
|
44
|
+
Mail.defaults do
|
45
|
+
delivery_method m, symbolize_keys(options)
|
46
|
+
end
|
47
|
+
end
|
25
48
|
|
26
49
|
def self.glob v = nil
|
27
50
|
if v
|
@@ -32,4 +55,3 @@ module Typedown2Blog
|
|
32
55
|
end
|
33
56
|
end
|
34
57
|
end
|
35
|
-
|
data/lib/typedown2blog.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
require 'typedown2blog/
|
3
|
-
require 'typedown2blog/
|
2
|
+
require 'typedown2blog/instance_exec.rb'
|
3
|
+
require 'typedown2blog/base.rb'
|
4
|
+
require 'typedown2blog/blog_post.rb'
|
5
|
+
require 'typedown2blog/formatters.rb'
|
4
6
|
require 'typedown2blog/spec.rb'
|
5
|
-
|
@@ -0,0 +1,21 @@
|
|
1
|
+
! Heading
|
2
|
+
|
3
|
+
//. A lead-in saying what the article is about.
|
4
|
+
Some more lead-in.
|
5
|
+
And more.
|
6
|
+
|
7
|
+
Some body copy.
|
8
|
+
|
9
|
+
!! Subheading
|
10
|
+
|
11
|
+
More body copy.
|
12
|
+
|
13
|
+
- Dialogue like this, he said. - I tell you.
|
14
|
+
|
15
|
+
- Oh, yeah?
|
16
|
+
|
17
|
+
More body copy. Standard markdown /italic/ and //bold//.
|
18
|
+
|
19
|
+
!! Another subheading
|
20
|
+
|
21
|
+
And body copy again.
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'typedown2blog'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
include Typedown2Blog
|
6
|
+
|
7
|
+
|
8
|
+
class TestBlogPost < Test::Unit::TestCase
|
9
|
+
context "BlogPost.new" do
|
10
|
+
setup do
|
11
|
+
@config = if(File.exists?("test/config.yaml"))
|
12
|
+
YAML.load_file("test/config.yaml")
|
13
|
+
else
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
config = @config
|
18
|
+
Mail.defaults do
|
19
|
+
case
|
20
|
+
when config["smtp"] then
|
21
|
+
delivery_method :smtp, { :smtp => "smtp.get.no" } #config["smtp"]
|
22
|
+
else
|
23
|
+
delivery_method :test
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
should "should accept parameters from a yaml file" do
|
29
|
+
assert_not_nil(@config, "needs a real mail account")
|
30
|
+
|
31
|
+
blog_post = BlogPost.new @config['blog']
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
should "should post a message" do
|
36
|
+
pending("needs a real mail account") unless @config
|
37
|
+
c = File.read_binary("test/data/example.tpd")
|
38
|
+
blog_post = BlogPost.new @config['blog']
|
39
|
+
blog_post.typedown_body c
|
40
|
+
blog_post.post!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/test/test_typedown2blog.rb
CHANGED
@@ -6,9 +6,9 @@ include Typedown2Blog
|
|
6
6
|
class TestTypedown2Blog < Test::Unit::TestCase
|
7
7
|
context "Parser" do
|
8
8
|
should "parse test mails without raising exceptions" do
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Dir.glob("./test/data/mail_*.eml") do |filename|
|
10
|
+
assert_nothing_raised do
|
11
|
+
convert_mail filename
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -16,7 +16,7 @@ class TestTypedown2Blog < Test::Unit::TestCase
|
|
16
16
|
|
17
17
|
context "Attached image" do
|
18
18
|
setup do
|
19
|
-
@mail =
|
19
|
+
@mail = convert_mail "./test/data/mail_0002.eml"
|
20
20
|
end
|
21
21
|
|
22
22
|
teardown do
|
@@ -34,14 +34,42 @@ class TestTypedown2Blog < Test::Unit::TestCase
|
|
34
34
|
end
|
35
35
|
|
36
36
|
context "Blog" do
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
setup do
|
38
|
+
Spec.setup do
|
39
|
+
blog do
|
40
|
+
mail_to "test@wrimle.com"
|
41
|
+
#format "wordpress"
|
42
|
+
#format "blogger"
|
43
|
+
end
|
44
|
+
mail_defaults do
|
45
|
+
delivery_method :test
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
should "post mails without raising exceptions" do
|
51
|
+
Spec.setup.blog do
|
52
|
+
format "wordpress"
|
53
|
+
end
|
54
|
+
|
55
|
+
Dir.glob("./test/data/*.eml") do |filename|
|
56
|
+
assert_nothing_raised do
|
57
|
+
Blog.post filename
|
41
58
|
end
|
42
|
-
#Blog.post "./test/data/mail_0002.eml"
|
43
59
|
end
|
44
60
|
end
|
45
61
|
|
62
|
+
should "post mails in blogger formatword without raising exceptions" do
|
63
|
+
Spec.setup.blog do
|
64
|
+
format "wordpress"
|
65
|
+
end
|
66
|
+
|
67
|
+
Dir.glob("./test/data/*.eml") do |filename|
|
68
|
+
assert_nothing_raised do
|
69
|
+
Blog.post filename
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
46
73
|
end
|
74
|
+
|
47
75
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typedown2blog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Rune Myrland
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-23 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -40,12 +40,12 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
hash:
|
43
|
+
hash: 9
|
44
44
|
segments:
|
45
45
|
- 0
|
46
46
|
- 0
|
47
|
-
-
|
48
|
-
version: 0.0.
|
47
|
+
- 11
|
48
|
+
version: 0.0.11
|
49
49
|
type: :runtime
|
50
50
|
version_requirements: *id002
|
51
51
|
- !ruby/object:Gem::Dependency
|
@@ -56,20 +56,34 @@ dependencies:
|
|
56
56
|
requirements:
|
57
57
|
- - ">="
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
hash:
|
59
|
+
hash: 21
|
60
60
|
segments:
|
61
61
|
- 0
|
62
62
|
- 0
|
63
|
-
-
|
64
|
-
version: 0.0.
|
63
|
+
- 5
|
64
|
+
version: 0.0.5
|
65
65
|
type: :runtime
|
66
66
|
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: mail_processor
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 27
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
- 0
|
79
|
+
- 2
|
80
|
+
version: 0.0.2
|
81
|
+
type: :runtime
|
82
|
+
version_requirements: *id004
|
67
83
|
description: The script will forward to the blog via a Mail2Blog interface.
|
68
84
|
email: rune@epubify.com
|
69
|
-
executables:
|
70
|
-
|
71
|
-
- control_typedown2blog_batcher.rb
|
72
|
-
- blog
|
85
|
+
executables: []
|
86
|
+
|
73
87
|
extensions: []
|
74
88
|
|
75
89
|
extra_rdoc_files:
|
@@ -82,18 +96,25 @@ files:
|
|
82
96
|
- README.rdoc
|
83
97
|
- Rakefile
|
84
98
|
- VERSION
|
85
|
-
- bin/blog
|
86
|
-
- bin/
|
87
|
-
- bin/
|
99
|
+
- example/bin/blog.rb
|
100
|
+
- example/bin/mail2test.rb
|
101
|
+
- example/bin/pop2blog.rb
|
102
|
+
- example/config/config.template.yaml
|
103
|
+
- example/script/db_init.rb
|
104
|
+
- example/test/data/example.tpd
|
88
105
|
- lib/typedown2blog.rb
|
89
|
-
- lib/typedown2blog/
|
90
|
-
- lib/typedown2blog/
|
106
|
+
- lib/typedown2blog/base.rb
|
107
|
+
- lib/typedown2blog/blog_post.rb
|
108
|
+
- lib/typedown2blog/formatters.rb
|
109
|
+
- lib/typedown2blog/instance_exec.rb
|
91
110
|
- lib/typedown2blog/spec.rb
|
111
|
+
- test/data/example.tpd
|
92
112
|
- test/data/mail_0001.eml
|
93
113
|
- test/data/mail_0002.eml
|
94
114
|
- test/data/mail_0002.jpg
|
95
115
|
- test/data/mail_0003.eml
|
96
116
|
- test/helper.rb
|
117
|
+
- test/test_blog_post.rb
|
97
118
|
- test/test_typedown2blog.rb
|
98
119
|
has_rdoc: true
|
99
120
|
homepage: http://github.com/wrimle/typedown2blog
|
@@ -132,3 +153,4 @@ summary: Email gateway for reformatting typedown documents before forwarding to
|
|
132
153
|
test_files:
|
133
154
|
- test/test_typedown2blog.rb
|
134
155
|
- test/helper.rb
|
156
|
+
- test/test_blog_post.rb
|
data/bin/blog
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'fileutils'
|
4
|
-
require 'rubygems'
|
5
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
-
require 'typedown2blog'
|
8
|
-
|
9
|
-
include Typedown2Blog
|
10
|
-
|
11
|
-
begin
|
12
|
-
require 'blog_config'
|
13
|
-
rescue MissingSourceFile => err
|
14
|
-
puts "Put your mail settings in blog_config.rb"
|
15
|
-
exit
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
unless Typedown2Blog::Blog.email
|
20
|
-
puts "#{__FILE__} blog_email incoming_mails_glob"
|
21
|
-
puts "Or specify in blog_config.rb"
|
22
|
-
exit
|
23
|
-
end
|
24
|
-
|
25
|
-
ARGV.each do |filename|
|
26
|
-
Blog.post filename
|
27
|
-
end
|
data/bin/typedown2blog_batcher
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'fileutils'
|
4
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
|
-
require 'rubygems'
|
7
|
-
require 'typedown2blog'
|
8
|
-
|
9
|
-
include Typedown2Blog
|
10
|
-
|
11
|
-
|
12
|
-
begin
|
13
|
-
require 'blog_config'
|
14
|
-
rescue MissingSourceFile => err
|
15
|
-
puts "Put your settings in blog_config.rb"
|
16
|
-
exit
|
17
|
-
end
|
18
|
-
|
19
|
-
puts Typedown2Blog::Blog.email
|
20
|
-
puts Typedown2Blog::Spec.glob
|
21
|
-
|
22
|
-
unless Typedown2Blog::Blog.email && Typedown2Blog::Spec.glob
|
23
|
-
puts "#{__FILE__} blog_email incoming_mails_glob"
|
24
|
-
puts "Or specify in blog_config.rb"
|
25
|
-
exit
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
|
-
loop do
|
30
|
-
# Read maildir and parse them if they are there
|
31
|
-
didWork = false
|
32
|
-
Dir.glob(Spec::glob) do |filename|
|
33
|
-
Blog.post filename
|
34
|
-
FileUtils::rm(filename)
|
35
|
-
didWork = true
|
36
|
-
end
|
37
|
-
|
38
|
-
# If no mails where found, sleep a bit before looking again
|
39
|
-
sleep(3) unless didWork
|
40
|
-
end
|
data/lib/typedown2blog/blog.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
|
3
|
-
module Typedown2Blog
|
4
|
-
class Blog
|
5
|
-
begin
|
6
|
-
@email = nil
|
7
|
-
end
|
8
|
-
|
9
|
-
|
10
|
-
def self.setup &block
|
11
|
-
instance_eval &block
|
12
|
-
end
|
13
|
-
|
14
|
-
|
15
|
-
def self.email v = nil
|
16
|
-
if v
|
17
|
-
@email = v
|
18
|
-
else
|
19
|
-
@email
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
|
24
|
-
def self.email= v
|
25
|
-
@email = v
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
|
-
def self.post filename
|
30
|
-
mail_to = @email
|
31
|
-
mail = Typedown2Blog::parse_mail filename do
|
32
|
-
to mail_to
|
33
|
-
|
34
|
-
typedown = text_part.body.decoded
|
35
|
-
typedown_root = Typedown::Section.sectionize(typedown, subject)
|
36
|
-
text_part.body = "#{typedown_root.body.to_html}\n\n"
|
37
|
-
end
|
38
|
-
mail.deliver!
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
|
3
|
-
require 'attachments'
|
4
|
-
require 'typedown'
|
5
|
-
|
6
|
-
module Typedown2Blog
|
7
|
-
|
8
|
-
def parse_mail filename, &block
|
9
|
-
out = nil
|
10
|
-
extract = Attachments::Extract.new [ "image/jpeg" ]
|
11
|
-
begin
|
12
|
-
out = Mail.new do
|
13
|
-
extract.parse filename
|
14
|
-
from extract.from
|
15
|
-
|
16
|
-
typedown_root = Typedown::Section.sectionize(extract.text_body, extract.subject)
|
17
|
-
|
18
|
-
subject typedown_root.title
|
19
|
-
text_part do
|
20
|
-
charset = 'UTF-8'
|
21
|
-
body typedown_root.body
|
22
|
-
end
|
23
|
-
|
24
|
-
extract.files.each do |f|
|
25
|
-
file = File.new(f[:tmpfile], "rb")
|
26
|
-
data = file.read()
|
27
|
-
file.close()
|
28
|
-
|
29
|
-
add_file(:filename => f[:save_as], :content => data )
|
30
|
-
attachments[f[:save_as]][:mime_type] = f[:mime_type]
|
31
|
-
|
32
|
-
#convert_to_multipart unless self.multipart?
|
33
|
-
#add_multipart_mixed_header
|
34
|
-
#attachments[f[:save_as]] = {
|
35
|
-
# :mime_type => f[:mime_type],
|
36
|
-
# :content => data,
|
37
|
-
#}
|
38
|
-
end
|
39
|
-
|
40
|
-
if block_given?
|
41
|
-
instance_eval &block
|
42
|
-
end
|
43
|
-
end
|
44
|
-
ensure
|
45
|
-
extract.close
|
46
|
-
end
|
47
|
-
out
|
48
|
-
end
|
49
|
-
|
50
|
-
|
51
|
-
def send_to_blog filename, secret_mail
|
52
|
-
mail = Typedown2Blog::parse_mail filename do
|
53
|
-
to secret_mail
|
54
|
-
|
55
|
-
typedown = text_part.body.decoded
|
56
|
-
typedown_root = Typedown::Section.sectionize(typedown, subject)
|
57
|
-
text_part.body = "#{typedown_root.body.to_html}\n\n"
|
58
|
-
end
|
59
|
-
mail.deliver!
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
def parse_glob glob_name, &block
|
65
|
-
didWork = false
|
66
|
-
Dir.glob(glob_name) do |filename|
|
67
|
-
block.call filename
|
68
|
-
didWork = true
|
69
|
-
end
|
70
|
-
|
71
|
-
didWork
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|