def publish_post(self, post): """Publishes a post. Args: post: post entity Returns: string, the Tumblr post id """ # TODO: expose as option # Attach these tags to the Tumblr posts. POST_TAGS = 'freedom.io' activity = post.to_activity() obj = activity['object'] date = util.parse_iso8601(activity['published']) location = obj.get('location') logging.info('Publishing post %s', obj['id']) # extract title title = obj.get('title') if not title: first_phrase = re.search('^[^,.:;?!]+', obj.get('content', '')) if first_phrase: title = first_phrase.group() elif location and 'displayName' in location: title = 'At ' + location['displayName'] else: title = date.date().isoformat() # date is UTC (ie GMT), formatted e.g. '2012-01-14 12:00:15 GMT' if date.utcoffset(): date = date - date.utcoffset() datestr_utc = date.strftime('%Y-%m-%d %H:%M:%S GMT') # post params: http://www.tumblr.com/docs/en/api/v2#posting body = post.render_html() params = { 'type': 'text', # 'tags': POST_TAGS, # TODO: ugh, tumblr doesn't let you create a post with a date more than an # hour off of the current time. bleh. # https://groups.google.com/d/msg/tumblr-api/CYLno2Q60sU/6tR1Xe56TiIJ # 'date': datestr_utc, 'format': 'html', # 'title': title, 'body': body, } # photo image_url = obj.get('image', {}).get('url') if obj.get('objectType') == 'photo' and image_url: params.update({ 'type': 'photo', 'source': image_url, 'caption': body, }) del params['body'] # del params['title'] # post! tp = tumblpy.Tumblpy(app_key=TUMBLR_APP_KEY, app_secret=TUMBLR_APP_SECRET, oauth_token=self.token_key, oauth_token_secret=self.token_secret) logging.info('Creating post with params: %r', params) resp = tp.post('post', blog_url=self.hostname(), params=params) return str(resp['id'])
def publish_post(self, post): """Publishes a post. Args: post: post entity Returns: string, the Blogger post id """ # TODO: expose as option # Attach these tags to the Blogger posts. POST_TAGS = ['freedom.io'] activity = post.to_activity() obj = activity['object'] date = util.parse_iso8601(activity['published']) location = obj.get('location') xmlrpc = XmlRpc(self.xmlrpc_url(), self.blog_id, self.username, self.password, verbose=True, transport=GAEXMLRPCTransport()) logging.info('Publishing post %s', obj['id']) # extract title title = obj.get('title') if not title: first_phrase = re.search('^[^,.:;?!]+', obj.get('content', '')) if first_phrase: title = first_phrase.group() elif location and 'displayName' in location: title = 'At ' + location['displayName'] else: title = date.date().isoformat() # photo image = obj.get('image', {}) image_url = image.get('url') if obj.get('objectType') == 'photo' and image_url: logging.info('Downloading %s', image_url) resp = urllib2.urlopen(image_url) data = resp.read() logging.debug('downloaded %d bytes', len(data)) filename = os.path.basename(urlparse.urlparse(image_url).path) mime_type = resp.info().gettype() logging.info('Sending uploadFile: %s %s', mime_type, filename) upload = xmlrpc.upload_file(filename, mime_type, data) image['url'] = upload['url'] # post! # http://codex.blogger.org/XML-RPC_Blogger_API/Posts#wp.newPost new_post_params = { 'post_type': 'post', 'post_status': 'publish', 'post_title': title, # leave this unset to default to the authenticated user # 'post_author': 0, 'post_content': post.render_html(), 'post_date': date, 'comment_status': 'open', # WP post tags are now implemented as taxonomies: # http://codex.blogger.org/XML-RPC_Blogger_API/Categories_%26_Tags 'terms_names': { 'post_tag': POST_TAGS }, } logging.info('Sending newPost: %r', new_post_params) post_id = xmlrpc.new_post(new_post_params) return str(post_id)
def publish_post(self, post): """Publishes a post. Args: post: post entity Returns: string, the WordPress post id """ # TODO: expose as option # Attach these tags to the WordPress posts. POST_TAGS = ['Freedom'] activity = post.to_activity() obj = activity['object'] date = util.parse_iso8601(activity['published']) location = obj.get('location') xmlrpc = XmlRpc(self.xmlrpc_url(), self.blog_id, self.username, self.password, verbose=True, transport=GAEXMLRPCTransport()) logging.info('Publishing post %s', obj['id']) # extract title title = obj.get('title') if not title: first_phrase = re.search('^[^,.:;?!]+', obj.get('content', '')) if first_phrase: title = first_phrase.group() elif location and 'displayName' in location: title = 'At ' + location['displayName'] else: title = date.date().isoformat() # photo image = obj.get('image', {}) image_url = image.get('url') if obj.get('objectType') == 'photo' and image_url: logging.info('Downloading %s', image_url) resp = urllib2.urlopen(image_url) data = resp.read() logging.debug('downloaded %d bytes', len(data)) filename = os.path.basename(urlparse.urlparse(image_url).path) mime_type = resp.info().gettype() logging.info('Sending uploadFile: %s %s', mime_type, filename) upload = xmlrpc.upload_file(filename, mime_type, data) image['url'] = upload['url'] # post! # http://codex.wordpress.org/XML-RPC_WordPress_API/Posts#wp.newPost new_post_params = { 'post_type': 'post', 'post_status': 'publish', 'post_title': title, # leave this unset to default to the authenticated user # 'post_author': 0, 'post_content': post.render_html(), 'post_date': date, 'comment_status': 'open', # WP post tags are now implemented as taxonomies: # http://codex.wordpress.org/XML-RPC_WordPress_API/Categories_%26_Tags 'terms_names': {'post_tag': POST_TAGS}, } logging.info('Sending newPost: %r', new_post_params) post_id = xmlrpc.new_post(new_post_params) return str(post_id)
class Blogger(models.Destination): """A Blogger blog. The key name is the blog hostname.""" owner_name = db.StringProperty(required=True) # the App Engine user id, ie users.get_current_user().user_id() gae_user_id = db.StringProperty(required=True) def hostname(self): return self.key().name() def display_name(self): return self.hostname() @classmethod def new(cls, handler, **kwargs): """Creates and saves a Blogger entity based on query parameters. Args: handler: the current webapp.RequestHandler kwargs: passed through to the Blogger() constructor Returns: Blogger """ return Blogger.get_or_insert( handler.request.get('host'), owner_name=handler.request.get('blogger_owner_name'), gae_user_id=users.get_current_user().user_id(), **kwargs) def publish_post(self, post): """Publishes a post. Args: post: post entity Returns: string, the Blogger post id """ # TODO: expose as option # Attach these tags to the Blogger posts. POST_TAGS = ['freedom.io'] activity = post.to_activity() obj = activity['object'] date = util.parse_iso8601(activity['published']) location = obj.get('location') xmlrpc = XmlRpc(self.xmlrpc_url(), self.blog_id, self.username, self.password, verbose=True, transport=GAEXMLRPCTransport()) logging.info('Publishing post %s', obj['id']) # extract title title = obj.get('title') if not title: first_phrase = re.search('^[^,.:;?!]+', obj.get('content', '')) if first_phrase: title = first_phrase.group() elif location and 'displayName' in location: title = 'At ' + location['displayName'] else: title = date.date().isoformat() # photo image = obj.get('image', {}) image_url = image.get('url') if obj.get('objectType') == 'photo' and image_url: logging.info('Downloading %s', image_url) resp = urllib2.urlopen(image_url) data = resp.read() logging.debug('downloaded %d bytes', len(data)) filename = os.path.basename(urlparse.urlparse(image_url).path) mime_type = resp.info().gettype() logging.info('Sending uploadFile: %s %s', mime_type, filename) upload = xmlrpc.upload_file(filename, mime_type, data) image['url'] = upload['url'] # post! # http://codex.blogger.org/XML-RPC_Blogger_API/Posts#wp.newPost new_post_params = { 'post_type': 'post', 'post_status': 'publish', 'post_title': title, # leave this unset to default to the authenticated user # 'post_author': 0, 'post_content': post.render_html(), 'post_date': date, 'comment_status': 'open', # WP post tags are now implemented as taxonomies: # http://codex.blogger.org/XML-RPC_Blogger_API/Categories_%26_Tags 'terms_names': { 'post_tag': POST_TAGS }, } logging.info('Sending newPost: %r', new_post_params) post_id = xmlrpc.new_post(new_post_params) return str(post_id) def publish_comment(self, comment): """Publishes a comment. Args: comment: comment entity Returns: string, the Blogger comment id """ obj = comment.to_activity()['object'] author = obj.get('author', {}) content = obj.get('content') if not content: logging.warning('Skipping empty comment %s', obj['id']) return logging.info('Publishing comment %s', obj['id']) xmlrpc = XmlRpc(self.xmlrpc_url(), self.blog_id, self.username, self.password, verbose=True, transport=GAEXMLRPCTransport()) try: comment_id = xmlrpc.new_comment( comment.dest_post_id, { 'author': author.get('displayName', 'Anonymous'), 'author_url': author.get('url'), 'content': comment.render_html(), }) except xmlrpclib.Fault, e: # if it's a dupe, we're done! if not (e.faultCode == 500 and e.faultString.startswith('Duplicate comment detected')): raise published = obj.get('published') if published: date = util.parse_iso8601(published) logging.info("Updating comment's time to %s", date) xmlrpc.edit_comment(comment_id, {'date_created_gmt': date}) return str(comment_id)
def publish_post(self, post): """Publishes a post. Args: post: post entity Returns: string, the Tumblr post id """ # TODO: expose as option # Attach these tags to the Tumblr posts. POST_TAGS = ['Freedom'] activity = post.to_activity() obj = activity['object'] date = util.parse_iso8601(activity['published']) location = obj.get('location') logging.info('Publishing post %s', obj['id']) # extract title title = obj.get('title') if not title: first_phrase = re.search('^[^,.:;?!]+', obj.get('content', '')) if first_phrase: title = first_phrase.group() elif location and 'displayName' in location: title = 'At ' + location['displayName'] else: title = date.date().isoformat() # date is UTC (ie GMT), formatted e.g. '2012-01-14 12:00:15 GMT' if date.utcoffset(): date = date - date.utcoffset() datestr_utc = date.strftime('%Y-%m-%d %H:%M:%S GMT') # post params: http://www.tumblr.com/docs/en/api/v2#posting body = post.render_html() params = { 'type': 'text', # 'tags': POST_TAGS, # TODO: ugh, tumblr doesn't let you create a post with a date more than an # hour off of the current time. bleh. # https://groups.google.com/d/msg/tumblr-api/CYLno2Q60sU/6tR1Xe56TiIJ # 'date': datestr_utc, 'format': 'html', # 'title': title, 'body': body, } # photo image_url = obj.get('image', {}).get('url') if obj.get('objectType') == 'photo' and image_url: params.update({'type': 'photo', 'source': image_url, 'caption': body, }) del params['body'] # del params['title'] # post! tp = tumblpy.Tumblpy(app_key=TUMBLR_APP_KEY, app_secret=TUMBLR_APP_SECRET, oauth_token=self.token_key, oauth_token_secret=self.token_secret) logging.info('Creating post with params: %r', params) resp = tp.post('post', blog_url=self.hostname(), params=params) return str(resp['id'])