typedown2blog 0.0.0 → 0.1.1
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/.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
|