git-svn-id: http://wordpress-library.googlecode.com/svn/trunk@2 c225be49-b319-0410...
[pyWpLib.git] / wordpresslib.py
blobaf331ccd1c30e3b0b99718228c17eb2fdab87411
1 """
2 wordpresslib.py
4 WordPress xml-rpc client library
5 use MovableType API
7 Copyright (C) 2005 Michele Ferretti
8 black.bird@tiscali.it
9 http://www.blackbirdblog.it
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 XML-RPC supported methods:
26 * getUsersBlogs
27 * getUserInfo
28 * getPost
29 * getRecentPosts
30 * newPost
31 * editPost
32 * deletePost
33 * newMediaObject
34 * getCategoryList
35 * getPostCategories
36 * setPostCategories
37 * getTrackbackPings
38 * publishPost
39 * getPingbacks
41 References:
42 * http://codex.wordpress.org/XML-RPC_Support
43 * http://www.sixapart.com/movabletype/docs/mtmanual_programmatic.html
44 * http://docs.python.org/lib/module-xmlrpclib.html
45 """
47 __author__ = "Michele Ferretti <black.bird@tiscali.it>"
48 __version__ = "$Revision: 1.0 $"
49 __date__ = "$Date: 2005/05/02 $"
50 __copyright__ = "Copyright (c) 2005 Michele Ferretti"
51 __license__ = "LGPL"
53 import exceptions
54 import re
55 import os
56 import xmlrpclib
57 import datetime
58 import time
60 class WordPressException(exceptions.Exception):
61 """Custom exception for WordPress client operations
62 """
63 def __init__(self, obj):
64 if isinstance(obj, xmlrpclib.Fault):
65 self.id = obj.faultCode
66 self.message = obj.faultString
67 else:
68 self.id = 0
69 self.message = obj
71 def __str__(self):
72 return '<%s %d: \'%s\'>' % (self.__class__.__name__, self.id, self.message)
74 class WordPressBlog:
75 """Represents blog item
76 """
77 def __init__(self):
78 self.id = ''
79 self.name = ''
80 self.url = ''
81 self.isAdmin = False
83 class WordPressUser:
84 """Represents user item
85 """
86 def __init__(self):
87 self.id = ''
88 self.firstName = ''
89 self.lastName = ''
90 self.nickname = ''
91 self.email = ''
93 class WordPressCategory:
94 """Represents category item
95 """
96 def __init__(self):
97 self.id = 0
98 self.name = ''
99 self.isPrimary = False
101 class WordPressPost:
102 """Represents post item
103 """
104 def __init__(self):
105 self.id = 0
106 self.title = ''
107 self.date = None
108 self.permaLink = ''
109 self.description = ''
110 self.textMore = ''
111 self.excerpt = ''
112 self.link = ''
113 self.categories = []
114 self.user = ''
115 self.allowPings = False
116 self.allowComments = False
119 class WordPressClient:
120 """Client for connect to WordPress XML-RPC interface
123 def __init__(self, url, user, password):
124 self.url = url
125 self.user = user
126 self.password = password
127 self.blogId = 0
128 self.categories = None
129 self._server = xmlrpclib.ServerProxy(self.url)
131 def _filterPost(self, post):
132 """Transform post struct in WordPressPost instance
134 postObj = WordPressPost()
135 postObj.permaLink = post['permaLink']
136 postObj.description = post['description']
137 postObj.title = post['title']
138 postObj.excerpt = post['mt_excerpt']
139 postObj.user = post['userid']
140 postObj.date = time.strptime(str(post['dateCreated']), "%Y%m%dT%H:%M:%S")
141 postObj.link = post['link']
142 postObj.textMore = post['mt_text_more']
143 postObj.allowComments = post['mt_allow_comments'] == 1
144 postObj.id = int(post['postid'])
145 postObj.categories = post['categories']
146 postObj.allowPings = post['mt_allow_pings'] == 1
147 return postObj
149 def _filterCategory(self, cat):
150 """Transform category struct in WordPressCategory instance
152 catObj = WordPressCategory()
153 catObj.id = int(cat['categoryId'])
154 catObj.name = cat['categoryName']
155 if cat.has_key('isPrimary'):
156 catObj.isPrimary = cat['isPrimary']
157 return catObj
159 def selectBlog(self, blogId):
160 self.blogId = blogId
162 def supportedMethods(self):
163 """Get supported methods list
165 return self._server.mt.supportedMethods()
167 def getLastPost(self):
168 """Get last post
170 return tuple(self.getRecentPosts(1))[0]
172 def getRecentPosts(self, numPosts=5):
173 """Get recent posts
175 try:
176 posts = self._server.metaWeblog.getRecentPosts(self.blogId, self.user,
177 self.password, numPosts)
178 for post in posts:
179 yield self._filterPost(post)
180 except xmlrpclib.Fault, fault:
181 raise WordPressException(fault)
183 def getPost(self, postId):
184 """Get post item
186 try:
187 return self._filterPost(self._server.metaWeblog.getPost(str(postId), self.user, self.password))
188 except xmlrpclib.Fault, fault:
189 raise WordPressException(fault)
191 def getUserInfo(self):
192 """Get user info
194 try:
195 userinfo = self._server.blogger.getUserInfo('', self.user, self.password)
196 userObj = WordPressUser()
197 userObj.id = userinfo['userid']
198 userObj.firstName = userinfo['firstname']
199 userObj.lastName = userinfo['lastname']
200 userObj.nickname = userinfo['nickname']
201 userObj.email = userinfo['email']
202 return userObj
203 except xmlrpclib.Fault, fault:
204 raise WordPressException(fault)
206 def getUsersBlogs(self):
207 """Get blog's users info
209 try:
210 blogs = self._server.blogger.getUsersBlogs('', self.user, self.password)
211 for blog in blogs:
212 blogObj = WordPressBlog()
213 blogObj.id = blog['blogid']
214 blogObj.name = blog['blogName']
215 blogObj.isAdmin = blog['isAdmin']
216 blogObj.url = blog['url']
217 yield blogObj
218 except xmlrpclib.Fault, fault:
219 raise WordPressException(fault)
221 def newPost(self, post, publish):
222 """Insert new post
224 blogContent = {
225 'title' : post.title,
226 'description' : post.description
229 # add categories
230 i = 0
231 categories = []
232 for cat in post.categories:
233 if i == 0:
234 categories.append({'categoryId' : cat, 'isPrimary' : 1})
235 else:
236 categories.append({'categoryId' : cat, 'isPrimary' : 0})
237 i += 1
239 # insert new post
240 idNewPost = int(self._server.metaWeblog.newPost(self.blogId, self.user, self.password, blogContent, 0))
242 # set categories for new post
243 self.setPostCategories(idNewPost, categories)
245 # publish post if publish set at True
246 if publish:
247 self.publishPost(idNewPost)
249 return idNewPost
251 def getPostCategories(self, postId):
252 """Get post's categories
254 try:
255 categories = self._server.mt.getPostCategories(postId, self.user,
256 self.password)
257 for cat in categories:
258 yield self._filterCategory(cat)
259 except xmlrpclib.Fault, fault:
260 raise WordPressException(fault)
262 def setPostCategories(self, postId, categories):
263 """Set post's categories
265 self._server.mt.setPostCategories(postId, self.user, self.password, categories)
267 def editPost(self, postId, post, publish):
268 """Edit post
270 blogcontent = {
271 'title' : post.title,
272 'description' : post.description,
273 'permaLink' : post.permaLink,
274 'mt_allow_pings' : post.allowPings,
275 'mt_text_more' : post.textMore,
276 'mt_excerpt' : post.excerpt
279 if post.date:
280 blogcontent['dateCreated'] = xmlrpclib.DateTime(post.date)
282 # add categories
283 i = 0
284 categories = []
285 for cat in post.categories:
286 if i == 0:
287 categories.append({'categoryId' : cat, 'isPrimary' : 1})
288 else:
289 categories.append({'categoryId' : cat, 'isPrimary' : 0})
290 i += 1
292 result = self._server.metaWeblog.editPost(postId, self.user, self.password,
293 blogcontent, 0)
295 if result == 0:
296 raise WordPressException('Post edit failed')
298 # set categories for new post
299 self.setPostCategories(postId, categories)
301 # publish new post
302 if publish:
303 self.publishPost(postId)
305 def deletePost(self, postId):
306 """Delete post
308 try:
309 return self._server.blogger.deletePost('', postId, self.user,
310 self.password)
311 except xmlrpclib.Fault, fault:
312 raise WordPressException(fault)
314 def getCategoryList(self):
315 """Get blog's categories list
317 try:
318 if not self.categories:
319 self.categories = []
320 categories = self._server.mt.getCategoryList(self.blogId,
321 self.user, self.password)
322 for cat in categories:
323 self.categories.append(self._filterCategory(cat))
325 return self.categories
326 except xmlrpclib.Fault, fault:
327 raise WordPressException(fault)
329 def getCategoryIdFromName(self, name):
330 """Get category id from category name
332 for c in self.getCategoryList():
333 if c.name == name:
334 return c.id
336 def getTrackbackPings(self, postId):
337 """Get trackback pings of post
339 try:
340 return self._server.mt.getTrackbackPings(postId)
341 except xmlrpclib.Fault, fault:
342 raise WordPressException(fault)
344 def publishPost(self, postId):
345 """Publish post
347 try:
348 return (self._server.mt.publishPost(postId, self.user, self.password) == 1)
349 except xmlrpclib.Fault, fault:
350 raise WordPressException(fault)
352 def getPingbacks(self, postUrl):
353 """Get pingbacks of post
355 try:
356 return self._server.pingback.extensions.getPingbacks(postUrl)
357 except xmlrpclib.Fault, fault:
358 raise WordPressException(fault)
360 def newMediaObject(self, mediaFileName):
361 """Add new media object (image, movie, etc...)
363 try:
364 f = file(mediaFileName, 'rb')
365 mediaBits = f.read()
366 f.close()
368 mediaStruct = {
369 'name' : os.path.basename(mediaFileName),
370 'bits' : xmlrpclib.Binary(mediaBits)
373 result = self._server.metaWeblog.newMediaObject(self.blogId,
374 self.user, self.password, mediaStruct)
375 return result['url']
377 except xmlrpclib.Fault, fault:
378 raise WordPressException(fault)