source: products/SimpleBlog/branches/plone-2.5/MetaWeblogAPI.py @ 3665

Last change on this file since 3665 was 1, checked in by myroslav, 18 years ago

Building directory structure

  • Property svn:eol-style set to native
File size: 11.0 KB
Line 
1#
2# Authors: Tom von Schwerdtner <tvon@etria.com>
3#          Brian Skahan <bskahan@etria.com>
4#
5# Copyright 2004, Etria, LLP
6#
7# This file is part of Quills
8#
9# Quills is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# Foobar is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with Quills; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
23
24from OFS.SimpleItem import SimpleItem
25from Products.CMFCore.utils import getToolByName
26from Products.CMFDefault.utils import parseHeadersBody
27from AccessControl import ClassSecurityInfo, getSecurityManager
28from AccessControl.SecurityManagement import setSecurityManager, newSecurityManager
29
30import DateTime
31import re
32import xmlrpclib
33import random
34
35authMethods = [
36    'metaWeblog/getPost',
37    'metaWeblog/deletePost',
38    'metaWeblog/editPost',
39    'metaWeblog/newPost',
40    'metaWeblog/getRecentPosts',
41    'metaWeblog/getUsersBlogs',
42    'metaWeblog/getCategories',
43    'metaWeblog/newMediaObject'
44    ]
45
46def genericMetaWeblogAuth(args):
47    return args[1], args[2], args
48
49
50class MetaWeblogAPI(SimpleItem):
51    """http://www.metaWeblog.com/developers/api/1_docs/"""
52    security = ClassSecurityInfo()
53
54    def __init__(self, RPCAuth = None):
55        ""
56        if RPCAuth:
57            self.setupRPCAuth(RPCAuth)
58       
59    security.declarePublic('setupRPCAuth')
60    def setupRPCAuth(self, RPCAuth):
61        RPCAuth.addAuthProvider(authMethods, genericMetaWeblogAuth)
62
63    security.declarePublic('newPost')
64    def newPost(self, blogid, username, password, struct, publish):
65        """Some Stuff"""
66       
67        self.plone_log('metaWeblog/newPost')
68        print 'metaWeblog/newPost'
69       
70        sbtool = getToolByName(self, 'simpleblog_tool')
71
72        blog = sbtool.getByUID(blogid)
73
74        body  = struct.get('description', struct.get('Description'))
75        title = struct.get('title', struct.get('Title'))
76        description = struct.get('mt_excerpt', '')
77        allow_comments = struct.get('mt_allow_comments', 1)
78       
79        id = sbtool.idFromTitle(title)
80
81        blog.invokeFactory('BlogEntry', id = id, title = title)
82        entry = getattr(blog, id)
83
84        entry.setBody(body, mimetype='text/html')
85        entry.setDescription(description)
86
87        # The workflow moves the entry, so get the UID now
88        entry_uid = entry.UID()
89
90        wf_tool = getToolByName(self, 'portal_workflow')
91        if publish:
92            state = sbtool.getPublishedState()
93            entry.setEffectiveDate(DateTime.DateTime())
94           
95            # todo xxxxxxxxxx
96            wf_tool.doActionFor(entry, 'publish', None)
97
98        return entry_uid
99
100    security.declarePublic('editPost')
101    def editPost(self, postid, username, password, struct, publish):
102        """Some stuff"""
103        self.plone_log('metaWeblog/editPost')
104        print 'metaWeblog/editPost'
105        sbtool = getToolByName(self, 'simpleblog_tool')
106       
107        entry = sbtool.getByUID(postid)
108
109        body  = struct.get('description', struct.get('Description'))   
110        title = struct.get('title', struct.get('Title'))
111        description = struct.get('mt_excerpt', '')
112        allow_comments = struct.get('mt_allow_comments', 1)
113       
114        entry.setBody(body, mimetype='text/html')
115        entry.setTitle(title)
116        entry.setDescription(description)
117        disc_tool = getToolByName(self, 'portal_discussion')
118       
119        #if allow_comments:
120            #disc_tool.overrideDiscussionFor(entry, 1)
121        #else:
122            #disc_tool.overrideDiscussionFor(entry, 0)
123 
124        #  portal.portal_workflow.getInfoFor(here,'review_state',None)   (from folder_contents.pt)
125        wf_tool=getToolByName(self, 'portal_workflow')
126        wf_state = wf_tool.getInfoFor(entry, 'review_state', '')
127        if publish and wf_state != 'published':  # todo!!!!
128            wf_tool.doActionFor(entry, 'publish')
129
130        entry.reindexObject()
131                   
132        return True
133       
134    security.declarePublic('getPost')
135    def getPost(self, postid, username, password):
136        "Return a post I suppose"
137        self.plone_log('metaWeblog/getPost')
138        print 'metaWeblog/getPost'
139        sbtool = getToolByName(self, 'simpleblog_tool')
140       
141        post = sbtool.getByUID(postid)
142        disc_tool = getToolByName(self, 'portal_discussion')
143        res = {}
144        if post:
145            res['postid'] = post.UID()
146            res['title'] = post.Title()
147            res['link'] = post.absolute_url()
148            res['category'] = post.listCategories()
149            res['categories'] = post.listCategories()
150            res['description'] = post.getBody()
151            res['mt_excerpt'] = post.Description()
152            res['mt_text_more']=post.getBody()
153            res['mt_allow_comments']=disc_tool.isDiscussionAllowedFor(post)
154               
155            return res
156        else:
157            raise AttributeError, "Post %s was not found" % postid
158
159        return res
160       
161    security.declarePublic('getCategories')
162    def getCategories(self, blogid, username, password):
163        "Returns a struct containing description, htmlUrl and rssUrl"
164        self.plone_log('metaWeblog/getCategories')
165        print 'metaWeblog/getCategories'
166        sbtool = getToolByName(self, 'simpleblog_tool')
167       
168        blog = sbtool.getByUID(blogid)
169       
170        cats = blog.listCategories()
171       
172        categories = []
173        for cat in cats:
174            categories.append(
175                {'categoryName': cat, 'description' : cat,
176                'htmlUrl' : blog.absolute_url() + ',/SimpleBlogCatSearch?category=' + cat,
177                'rssUrl' : blog.absolute_url() + ',/SimpleBlogCatSearch?category=' + cat
178                })
179               
180        self.plone_log('metaWeblog/getCategories: returning ', categories)
181        return categories
182
183    security.declarePublic('deletePost')
184    def deletePost(self, postid, username, password, publish):
185        "Returns true on success, fault on failure"
186        self.plone_log('metaWeblog/deletePost')
187        print 'metaWeblog/deletePost'
188        sbtool = getToolByName(self, 'simpleblog_tool')
189       
190        entry = sbtool.getByUID(postid)
191
192        entry.aq_inner.aq_parent.manage_delObjects(entry.getId())
193
194        return True
195
196    security.declarePublic('getRecentPosts')
197    def getRecentPosts(self, blogid, username, password, num):
198        """Return 'num' recent posts to specified blog, returns a struct:
199         The three basic elements are title, link and description.
200         For blogging tools that don't support titles and links, the description element holds what the Blogger API refers to as 'content'."""
201
202        self.plone_log('metaWeblog/getRecentPosts')
203        print 'metaWeblog/getRecentPosts'
204        sbtool = getToolByName(self, 'simpleblog_tool')
205        blog = sbtool.getByUID(blogid)
206
207        entries = blog.getFolderListingFolderContents(contentFilter={'portal_type': 'BlogEntry'},)       
208        # todo: what if entries are in subfolders?
209       
210        posts = []
211        for entry in entries:
212            posts.append( { 'dateCreated':entry.created()
213                            , 'userid':entry.Creator()
214                            , 'postid':entry.UID()
215                            , 'title':entry.Title()
216                            , 'description':entry.getBody()
217                            , 'excerpt':entry.Description()
218                              })           
219           
220        if num is not None:
221            return posts[:int(num)]
222        return posts
223   
224    security.declarePublic('getUsersBlogs')
225    def getUsersBlogs(self, username, password):
226        """ Return all the blogs the user has access and write permission to """
227
228        self.plone_log('metaWeblog/getUsersBlogs')
229        print 'metaWeblog/getUsersBlogs'
230        catalog = getToolByName(self, 'portal_catalog')
231        results = catalog(meta_type='Blog')
232
233        blogs = []
234        for item in results:
235            o = item.getObject()
236            if o.portal_membership.checkPermission('Modify portal content', o):
237                blogs.append(
238                        {'url': o.absolute_url(),
239                         'blogid' : o.UID(),
240                         'blogName' : o.title_or_id()}
241                        )
242
243        return blogs
244
245    security.declarePublic('getUserInfo')
246    def getUserInfo(self, appkey, username, password):
247        """metaWeblog.getUserInfo returns a struct containing user's
248        userid, firstname, lastname, nickname, email, and url."""
249        self.plone_log('metaWeblog/getUserInfo')
250        print 'metaWeblog/getUserInfo'
251
252        membership=getToolByName(self, 'portal_membership')
253        info={'name':'no name','email':'no email','userid':'no user id'
254               ,'firstname':'no first name','lastname':'no last name'
255               ,'url':'no url'}
256        member=membership.getAuthenticatedMember()
257        if member:
258            for key,value in info.items():
259                info[key] = getattr(member,key,None) or value
260        return info
261
262
263    security.declarePublic('newMediaObject')
264    def newMediaObject(self, blogid, username, password, struct):
265        """Create media object and return it's URL or exception"""
266       
267        self.plone_log('metaWeblog/newMediaObject')
268        print 'metaWeblog/newMediaObject'
269       
270        sbtool = getToolByName(self, 'simpleblog_tool')
271        blog = sbtool.getByUID(blogid)
272       
273        media_name = struct.get('name', None)
274        mime_type = struct.get('type', None)
275        data = struct.get('bits', '')
276
277        if not media_name or media_name.startswith('.'):
278            raise AttributeError, "No 'name' of media object supply or starts with '.'"
279        if not mime_type:
280            raise AttributeError, "No 'type' of media object supply"
281        if not (mime_type.startswith('image') or mime_type.startswith('application')):
282            raise AttributeError, "'%s' - not supported mime tipe." % mime_type
283
284        if not 'images' in blog.objectIds():
285            blog.invokeFactory('BlogFolder', id = 'images', title='Container for images')
286            images = getattr(blog, 'images')
287        else:
288            images = blog.images
289
290        id = re.sub('[^A-Za-z0-9_.]', '', re.sub(' ', '_', media_name)).lower()
291        while id in images.objectIds():
292            index = id.rfind('.')
293            if index > -1:
294                front = id[:index]
295                ext = id[index:]
296            else:
297                front = id
298                ext = ''
299            id = front + str(random.randint(1,100)) + ext
300
301        images.invokeFactory('Image', id=id, title=media_name, file=str(data)) 
302        image = getattr(images, id)
303
304        return {'url':image.absolute_url()}
Note: See TracBrowser for help on using the repository browser.