movabletype 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
@@ -0,0 +1 @@
1
+ * MovableType API for Ruby
@@ -0,0 +1,74 @@
1
+ require 'xmlrpc/client'
2
+ require 'movabletype/post'
3
+ module MovableType
4
+ class Entry
5
+ class NoPostId < StandardError
6
+ end
7
+ Category = Struct.new('Category',:id,:name)
8
+
9
+ def initialize(entry,blogid,user,passwd)
10
+ @entry = XMLRPC::Client.new2 entry
11
+ @metaWeblog = @entry.proxy('metaWeblog')
12
+ @mt = @entry.proxy('mt')
13
+ @blogid = blogid
14
+ @user = user
15
+ @passwd = passwd
16
+ end
17
+
18
+ # create new article.
19
+ # and return new article.
20
+ def post(post,publish=true)
21
+ new_post = post.dup
22
+ post!(new_post,publish)
23
+ new_post
24
+ end
25
+
26
+ def post!(post,publish=true)
27
+ postid = @metaWeblog.newPost @blogid,@user,@passwd,
28
+ post.to_struct,publish
29
+ post.id = postid
30
+ end
31
+
32
+ def edit(post,publish=true)
33
+ post.id != nil or raise NoPostId.new
34
+ @metaWeblog.editPost post.id,@user,@passwd,post.to_struct,publish
35
+ end
36
+
37
+ def delete(post,publish=true)
38
+ post.id != nil or raise NoPostId.new
39
+ @entry.call 'blogger.deletePost','hoge',post.id,@user,@passwd,publish
40
+ end
41
+
42
+ def publish(post)
43
+ post.id != nil or raise NoPostId.new
44
+ @mt.publishPost post.id,@user,@passwd
45
+ end
46
+
47
+ def categories(post)
48
+ post.id != nil or raise NoPostId.new
49
+ @mt.getPostCategories(post.id,@user,@passwd).map{|category|
50
+ Category.new category['categoryId'],category['categoryName']
51
+ }
52
+ end
53
+
54
+ def set_categories(post,*categories)
55
+ post.id != nil or raise NoPostId.new
56
+ @mt.setPostCategories post.id,@user,@passwd,categories.map{|category|
57
+ {'categoryId'=>category.id}
58
+ }
59
+ end
60
+
61
+ def recent_post(size)
62
+ result = @metaWeblog.getRecentPosts @blogid,@user,@passwd,size
63
+ result.map{|content|
64
+ Post.new2 content
65
+ }
66
+ end
67
+
68
+ def category_list
69
+ @mt.getCategoryList(@blogid,@user,@passwd).map{|struct|
70
+ Category.new(struct['categoryId'],struct['categoryName'])
71
+ }
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,136 @@
1
+ require 'time'
2
+
3
+ module MovableType
4
+ class Post
5
+ Method2Struct = {
6
+ :title=>'title',
7
+ :description => 'description',
8
+ :date => 'dateCreated',
9
+ 'comment?'.intern => 'mt_allow_comments',
10
+ 'trackback?'.intern => 'mt_allow_pings',
11
+ :break => 'mt_convert_breaks',
12
+ :text_more => 'mt_text_more',
13
+ :excerpt => 'mt_excerpt',
14
+ :keywords => 'mt_keywords',
15
+ :trackbacks => 'mt_tb_ping_urls'
16
+ }
17
+ Struct2Option = Method2Struct.invert
18
+ Struct2Option.delete('title')
19
+ Struct2Option.delete('description')
20
+ Struct2Option['mt_allow_comments'] = :comment
21
+ Struct2Option['mt_allow_pings'] = :trackback
22
+ Struct2Option['postid'] = :id
23
+
24
+
25
+ def self.new2(struct,id=nil)
26
+ title = struct['title']
27
+ description = struct['description']
28
+ option = {}
29
+ Struct2Option.each{|field,name|
30
+ res = struct[field]
31
+ option[name] = case res
32
+ when 1
33
+ true
34
+ when 0
35
+ false
36
+ when 'none'
37
+ :none
38
+ when '0'
39
+ :none
40
+ when 'convert_breaks'
41
+ :convert
42
+ when '1'
43
+ :convert
44
+ when nil
45
+ else
46
+ if name == :keywords
47
+ res.split ','
48
+ else
49
+ res
50
+ end
51
+ end
52
+ }
53
+ if id then
54
+ option[:id] =id
55
+ end
56
+ self.new title,description,option
57
+ end
58
+
59
+ def self.option_get(*ids)
60
+ for id in ids
61
+ module_eval <<-"END"
62
+ def #{id}
63
+ if @option.key? :#{id} then
64
+ @option[:#{id}]
65
+ else
66
+ nil
67
+ end
68
+ end
69
+ END
70
+ end
71
+ end
72
+
73
+ def self.option_is(*ids)
74
+ for id in ids
75
+ module_eval <<-"END"
76
+ def #{id}?
77
+ if @option.key? :#{id} then
78
+ @option[:#{id}]
79
+ else
80
+ nil
81
+ end
82
+ end
83
+ END
84
+ end
85
+ end
86
+
87
+ attr_reader :title,:description
88
+ attr_accessor :id
89
+ option_get :date,:break,:text_more,:excerpt,:keywords,:trackbacks
90
+ option_is :comment,:trackback
91
+ def initialize(title,description,option={:date=>Time.now})
92
+ @title = title
93
+ @description = description
94
+ @option = option
95
+ @id = option[:id]
96
+ end
97
+
98
+ def ==(o)
99
+ eq = [:class,:title,:description,:id,
100
+ :date,:break,:text_more,:excerpt,:keywords,:trackbacks,
101
+ 'comment?','trackback?']
102
+
103
+ eq.each{|method|
104
+ unless o.send(method) == self.send(method) then
105
+ return false
106
+ end
107
+ }
108
+ return true
109
+ end
110
+
111
+ def to_struct
112
+ hash = {}
113
+ Method2Struct.each do |method,field|
114
+ res = self.send method
115
+ case res
116
+ when true
117
+ hash[field] = 1
118
+ when false
119
+ hash[field] = 0
120
+ when :none
121
+ hash[field] = 'none'
122
+ when :convert
123
+ hash[field] = 'convert_breaks'
124
+ when nil
125
+ else
126
+ if method == :keywords
127
+ hash[field] = res.join(',')
128
+ else
129
+ hash[field] = res
130
+ end
131
+ end
132
+ end
133
+ hash
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,2 @@
1
+ require 'movabletype/post'
2
+ require 'movabletype/entry'
@@ -0,0 +1,130 @@
1
+ require 'test/unit'
2
+ require 'movabletype/entry'
3
+
4
+ class XMLRPC::Client
5
+ alias_method :_initialize_,:initialize
6
+ @@history = []
7
+ def initalize(*args,&block)
8
+ _initialize_ *args,&block
9
+ end
10
+
11
+ def getRecentPosts(blogid,username,password,size)
12
+ Array.new(size){|i|
13
+ MovableType::Post.new("title#{i}","body#{i}",{:id=>i.to_s}).to_struct
14
+ }
15
+ end
16
+
17
+ def getCategoryList(blogid,user,passwd)
18
+ [{'categoryId'=>'100','categoryName'=>'foo'},
19
+ {'categoryId'=>'101','categoryName'=>'bar'}]
20
+ end
21
+
22
+ def getPostCategories(postid,username,passwd)
23
+ [{'categoryId'=>'100','categoryName'=>'foo'},
24
+ {'categoryId'=>'101','categoryName'=>'bar'}]
25
+ end
26
+
27
+ def call(name,*args,&block)
28
+ mapping = {'metaWeblog.getRecentPosts'=> :getRecentPosts,
29
+ 'mt.getCategoryList' => :getCategoryList,
30
+ 'mt.getPostCategories'=>:getPostCategories}
31
+ @@history << [name,args].flatten
32
+ if mapping.key? name then
33
+ self.send mapping[name],*args
34
+ else
35
+ :hoge
36
+ end
37
+ end
38
+
39
+ def self.last
40
+ @@history[-1]
41
+ end
42
+
43
+ def self.last_method
44
+ @@history[-1][0]
45
+ end
46
+ end
47
+
48
+ class MovableTypeTest < Test::Unit::TestCase
49
+ Entry = 'http://example.com/mt.cgi'
50
+ BlogId = 4
51
+ Username = 'MIZUNO'
52
+ Passwd = 'Hiroki'
53
+
54
+ def setup
55
+ @post = MovableType::Post.new 'title','body'
56
+ @mt = MovableType::Entry.new(Entry,BlogId,Username,Passwd)
57
+ end
58
+
59
+ def test_post
60
+ new_post = @mt.post @post,true
61
+ assert_equal 'metaWeblog.newPost',XMLRPC::Client.last_method
62
+ assert_not_equal nil,new_post.id
63
+ assert_equal nil,@post.id
64
+ end
65
+
66
+ def test_edit
67
+ assert_raise(MovableType::Entry::NoPostId){
68
+ @mt.edit @post
69
+ }
70
+ @mt.edit MovableType::Post.new2(@post.to_struct,'100')
71
+ assert_equal 'metaWeblog.editPost',XMLRPC::Client.last_method
72
+ end
73
+
74
+ def test_delete
75
+ assert_raise(MovableType::Entry::NoPostId){
76
+ @mt.delete @post
77
+ }
78
+ @mt.delete MovableType::Post.new(nil,nil,{:id=>'100'})
79
+ assert_equal 'blogger.deletePost',XMLRPC::Client.last_method
80
+ end
81
+
82
+ def test_recent
83
+ posts = @mt.recent_post 2
84
+ assert_equal 'metaWeblog.getRecentPosts',XMLRPC::Client.last_method
85
+ assert_equal 2,posts.size
86
+ assert_equal 'title0',posts[0].title
87
+ assert_equal 'body0',posts[0].description
88
+ assert_equal 'title1',posts[1].title
89
+ assert_equal 'body1',posts[1].description
90
+ end
91
+
92
+ def test_publish
93
+ assert_raise(MovableType::Entry::NoPostId){
94
+ @mt.delete @post
95
+ }
96
+ @mt.publish MovableType::Post.new(nil,nil,{:id=>'100'})
97
+ assert_equal 'mt.publishPost',XMLRPC::Client.last_method
98
+ end
99
+
100
+ def test_set_categories
101
+ assert_raise(MovableType::Entry::NoPostId){
102
+ @mt.set_categories @post,'100','200'
103
+ }
104
+ cat = @mt.set_categories(
105
+ MovableType::Post.new(nil,nil,{:id=>'100'}),
106
+ MovableType::Entry::Category.new('100','foo'),
107
+ MovableType::Entry::Category.new('101','bar'))
108
+ assert_equal 'mt.setPostCategories',XMLRPC::Client.last_method
109
+ end
110
+
111
+ def test_categories
112
+ assert_raise(MovableType::Entry::NoPostId){
113
+ @mt.categories @post
114
+ }
115
+ cat = @mt.categories(MovableType::Post.new(nil,nil,{:id=>'100'})).sort{|a,b|
116
+ a.id <=> b.id}
117
+ assert_equal 'mt.getPostCategories',XMLRPC::Client.last_method
118
+ assert_equal 2,cat.size
119
+ assert_equal MovableType::Entry::Category.new('100','foo'),cat[0]
120
+ assert_equal MovableType::Entry::Category.new('101','bar'),cat[1]
121
+ end
122
+
123
+ def test_category_list
124
+ cat = @mt.category_list.sort{|a,b| a.id <=> b.id}
125
+ assert_equal 'mt.getCategoryList',XMLRPC::Client.last_method
126
+ assert_equal 2,cat.size
127
+ assert_equal MovableType::Entry::Category.new('100','foo'),cat[0]
128
+ assert_equal MovableType::Entry::Category.new('101','bar'),cat[1]
129
+ end
130
+ end
data/test/test_post.rb ADDED
@@ -0,0 +1,149 @@
1
+ require 'test/unit'
2
+ require 'movabletype/post'
3
+ class PostTest < Test::Unit::TestCase
4
+ def setup
5
+ @now = Time.now
6
+ @method = []
7
+ @struct = []
8
+ @klass = []
9
+
10
+ @struct.push({'title'=>'hoge','description'=>'baz','dateCreated'=>@now})
11
+ @method.push({:id=>nil,:title=>'hoge',:description=>'baz',:date=>@now})
12
+ @klass.push MovableType::Post.new('hoge','baz',{:date=>@now})
13
+
14
+ @struct.push({'title'=>'hoge','description'=>'baz','dateCreated'=>@now,
15
+ 'mt_convert_breaks'=>'none'})
16
+ @method.push({:id=>nil,:title=>'hoge',:description=>'baz',:date=>@now,
17
+ :break=>:none})
18
+ @klass.push MovableType::Post.new('hoge','baz',{:date=>@now,:break=>:none})
19
+
20
+ @struct.push({'title'=>'hoge','description'=>'baz','dateCreated'=>@now,
21
+ 'mt_convert_breaks'=>'convert_breaks'})
22
+ @method.push({:id=>nil,:title=>'hoge',:description=>'baz',:date=>@now,
23
+ :break=>:convert})
24
+ @klass.push MovableType::Post.new('hoge','baz',{:date=>@now,:break=>:convert})
25
+
26
+ @struct.push({'title'=>'hoge',
27
+ 'description'=>'baz',
28
+ 'dateCreated'=>@now})
29
+ @method.push({:id=>'100',:title=>'hoge',:description=>'baz',:date=>@now})
30
+ @klass.push MovableType::Post.new('hoge','baz',{:date=>@now,:id=>'100'})
31
+
32
+ @struct.push({'title'=>'hoge',
33
+ 'description'=>'baz',
34
+ 'dateCreated'=>@now,
35
+ 'mt_text_more'=>'more'})
36
+ @method.push({:title=>'hoge',
37
+ :description=>'baz',
38
+ :date=>@now,
39
+ :text_more=>'more',
40
+ :id=>nil})
41
+ @klass.push MovableType::Post.new('hoge','baz',
42
+ {:date=>@now,:text_more=>'more'})
43
+
44
+ @struct.push({'title'=>'hoge',
45
+ 'description'=>'baz',
46
+ 'dateCreated'=>@now,
47
+ 'mt_allow_comments'=>1})
48
+ @method.push({:title=>'hoge',
49
+ :description=>'baz',
50
+ :date=>@now,
51
+ 'comment?'.intern=>true,
52
+ :id=>nil})
53
+ @klass.push MovableType::Post.new('hoge','baz',
54
+ {:date=>@now,:comment=>true})
55
+
56
+ @struct.push({'title'=>'hoge',
57
+ 'description'=>'baz',
58
+ 'dateCreated'=>@now,
59
+ 'mt_allow_comments'=>1,
60
+ 'mt_allow_pings'=>0,
61
+ 'mt_convert_breaks'=>'none',
62
+ 'mt_text_more'=>'more',
63
+ 'mt_excerpt'=>'excerpt',
64
+ 'mt_keywords'=>'a,b,c',
65
+ 'mt_tb_ping_urls'=>['A','B','C']})
66
+ @method.push({:title=>'hoge',
67
+ :description=>'baz',
68
+ :date=>@now,
69
+ 'comment?'.intern=>true,
70
+ 'trackback?'.intern=>false,
71
+ :break=>:none,
72
+ :text_more=>'more',
73
+ :excerpt=>'excerpt',
74
+ :keywords=>['a','b','c'],
75
+ :trackbacks=>['A','B','C'],
76
+ :id=>nil})
77
+
78
+ @klass.push MovableType::Post.new('hoge','baz',
79
+ {:date=>@now,
80
+ :comment=>true,
81
+ :trackback=>false,
82
+ :break=>:none,
83
+ :text_more=>'more',
84
+ :excerpt=>'excerpt',
85
+ :keywords=>['a','b','c'],
86
+ :trackbacks=>['A','B','C']})
87
+ end
88
+
89
+ def test_to_struct
90
+ each_with(@struct,@klass){|s,k|
91
+ assert_equal_array s,k.to_struct
92
+ }
93
+ end
94
+
95
+ def assert_equal_array(expect,actual)
96
+ each_with(expect.to_a.sort,actual.to_a.sort){|e,a|
97
+ assert_equal e,a
98
+ }
99
+ end
100
+
101
+ def test_method
102
+ each_with(@klass,@method){|k,m|
103
+ m.each{|name,expect|
104
+ assert_equal expect,k.send(name)
105
+ }
106
+ }
107
+ end
108
+
109
+ def test_convert_none
110
+ struct = {'title'=>'hoge','description'=>'baz','dateCreated'=>@now,
111
+ 'mt_convert_breaks'=>'0'}
112
+ post = MovableType::Post.new('hoge','baz',{:date=>@now,:break=>:none})
113
+ assert_equal post,MovableType::Post.new2(struct)
114
+ end
115
+
116
+ def test_convert_conv
117
+ struct = {'title'=>'hoge','description'=>'baz','dateCreated'=>@now,
118
+ 'mt_convert_breaks'=>'1'}
119
+ post = MovableType::Post.new('hoge','baz',{:date=>@now,:break=>:convert})
120
+ assert_equal post,MovableType::Post.new2(struct)
121
+ end
122
+
123
+ def test_from_struct
124
+ each_with(@klass,@struct){|k,s|
125
+ assert_equal k,MovableType::Post.new2(s,k.id)
126
+ }
127
+ end
128
+
129
+ def each_with(klass1,klass2)
130
+ assert_equal klass1.length,klass2.length
131
+ klass1.each_index{|i|
132
+ yield klass1[i],klass2[i]
133
+ }
134
+ end
135
+
136
+ def test_date
137
+ post = MovableType::Post.new('tilte','description')
138
+ assert_not_equal nil,post.date
139
+
140
+ post = MovableType::Post.new('tilte','description')
141
+ assert_not_equal nil,post.to_struct['dateCreated']
142
+
143
+ post = MovableType::Post.new('tilte','description',{:date=>nil})
144
+ assert_equal nil,post.date
145
+
146
+ post = MovableType::Post.new('tilte','description',{:date=>nil})
147
+ assert_equal nil,post.to_struct['dateCreated']
148
+ end
149
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: movabletype
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2006-08-14 00:00:00 +09:00
8
+ summary: MovableType API for Ruby
9
+ require_paths:
10
+ - lib
11
+ email: hiroki1124@gmail.com
12
+ homepage: http://d.hatena.ne.jp/mzp/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - MIZUNO Hiroki
30
+ files:
31
+ - test/test_entry.rb
32
+ - test/test_post.rb
33
+ - lib/movabletype.rb
34
+ - lib/movabletype/entry.rb
35
+ - lib/movabletype/post.rb
36
+ - README
37
+ test_files:
38
+ - test/test_entry.rb
39
+ - test/test_post.rb
40
+ rdoc_options:
41
+ - --main
42
+ - README
43
+ extra_rdoc_files:
44
+ - README
45
+ executables: []
46
+
47
+ extensions: []
48
+
49
+ requirements: []
50
+
51
+ dependencies: []
52
+