movabletype 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+