#!/usr/bin/env python2.5 # -*- coding: utf-8 -*- """ Import text and images from a WordPress post. Ask logina name, password anda post ID. By prof. MS. José Antonio Meira da Rocha mailto:joseantoniomeira@gmail.com http://meiradarocha.jor.br License GPL 2.0 2010-01-25a Bugs: """ ############################## # Import Python system ############################## import sys ############################## # Assure is running in Scribus ############################## try: import scribus except ImportError,err: print "This Python script is written for the Scribus scripting interface." print "It can only be run from within Scribus." sys.exit(1) ######################### # USER IMPORTS GO HERE # ######################### import xmlrpclib import urllib from HTMLParser import HTMLParser from scribus import UNIT_MILLIMETERS, BUTTON_OK, BUTTON_NO, BUTTON_ABORT, ICON_WARNING, mm, pt ################################################ # User can change this constants ################################################ anteTitleStyle = "Antetitulo" titleStyle = "Titulo 1" estiloDoSubtitulo = "Subtitulo 1" authorStyle = "Assinatura" firstParagraphStyle = "Primeiro Paragrafo" defaultStyle = "Normal" captionStyle = 'Legenda' creditStyle = 'Credito da foto' wp_site = 'http://' loginname = '' password = '' postID = '' imageTypes = '*.jpg *.jpeg' captionHeight = 5 gutter = 5 #14.1732pt, 5mm ########################################## # Scribus constants that can't be modified AROUND_FRAME = 1 BOUNDING_BOX = 2 CONTOUR_LINE = 3 SCALETOFRAME = 1 FREESCALE = 0 PROPORTIONAL = 1 DISTORTED = 0 ###################### # Locale strings # Textos para tradução ###################### # Strings for no doc opened openDocCaption = 'Abra um documento' openDocMessage = "

Abra um documento

" \ +"Ops! Abra um documento antes \nde rodar este comando." # General caption generalCaption = "Formatar post" askFrameMessage = "

Selecione um quadro

" \ +"

Ops! Desenhe ou selecione apenas um quadro
" \ +"da matéria em que você quer aplicar estilos." # Strings about number of columns askColumnsCaption = 'Colunas' #Number of columns askColumnsMessage = '

Colunas

Quantas colunas?

' #How many columns? # Strings to askLoginData askLoginDataCaption = 'Entre seu login name' askLoginDataMessage = '

Entre seu login name

Entre seu nome de login no blog:

' getPasswordCaption = 'Entre sua senha' getPasswordMessage = '

Entre sua senha

Entre sua senha no blog:

' #Strings to askPostID askPostIDCaption = 'Entre o ID do post' askPostIDMessage = '

Entre o ID do post

Escreva o número ID do seu post no blog.

' # Error if less than 4 text lines lessThan4LinesCaption = "Coloque texto" lessThan4LinesMessage = "

Coloque texto

Por favor, coloque mais de quatro parágrafos neste quadro.

" cantLoadCaption = "Não pude caarregar o post" cantLoadMessage = "

Não pude caarregar o post/h2>

Não pude carregar o texto do post por problema de conexão
ou problemas de nome e senha.

" buildPhotoCaption = "Baixa a foto?" buildPhotoMessage = "

Baixa a foto?

Você quer baixar a foto: " saveImageCaption = "Grava a imagem" failPhotoCaption='Falhou o download da foto' failPhotoMessage='

Falhei em baixar a foto!

Que vergonha! Mas tentarei continuar trabalhando...

', defaultText = "Título\nSubtítulo\nAutor da matéria\nemail@doautor.com\nPrimeiro Parágrafo\nOutros parágrafos\nOutros parágrafos..." statusMessage = "Rodando o script..." # # End Locale strings #################### ########################## # Load WordPress post ########################## def loadWPpost(textFrame): server = xmlrpclib.ServerProxy( wp_site+"/xmlrpc.php" ) loginname = '' password = '' loginname,password = askLoginData(loginname,password) postID = 1 postID = askPostID(postID) try: post = server.metaWeblog.getPost(postID, loginname, password) except: scribus.messageBox(cantLoadCaption,cantLoadMessage,ICON_WARNING,BUTTON_OK) sys.exit() scribus.deleteText(textFrame) #applyStyle(defaultStyle,textFrame) ########################################## categories = ', '.join(post['categories']) length = len(categories) cursor = scribus.getTextLength(textFrame) scribus.insertText(categories+'\n',-1,textFrame) scribus.deselectAll() # Needs deselect prior select scribus.selectText(cursor,length,textFrame) applyStyle(anteTitleStyle,textFrame) ##################### title = post['title'] title = cleanText(title) length = len(title) cursor = scribus.getTextLength(textFrame) scribus.insertText(title+'\n',-1,textFrame) scribus.deselectAll() scribus.selectText(cursor,length,textFrame) applyStyle(titleStyle,textFrame) ####################################### author = post['wp_author_display_name'] length = len(author) cursor = scribus.getTextLength(textFrame) scribus.insertText(author+'\n',-1,textFrame) scribus.deselectAll() scribus.selectText(cursor,length,textFrame) applyStyle(authorStyle,textFrame) #################################### firstParagraph = post['description'] firstParagraph = reformWPtags(firstParagraph) parse.cursor = scribus.getTextLength(textFrame) #cursor = parse.cursor lines = firstParagraph.splitlines(1) for line in lines: if line != '\n': try: parse.feed(line) except: pass ########################### text = post['mt_text_more'] text = reformWPtags(text) parse.cursor = scribus.getTextLength(textFrame) lines = text.splitlines(1) for line in lines: if line != '\n': try: parse.feed(line) except: pass ############################## # Ask data about blog and post ############################## def askLoginData(loginname,password): l = scribus.valueDialog( askLoginDataCaption, askLoginDataMessage, loginname) p = scribus.valueDialog( getPasswordCaption, getPasswordMessage, password) return l,p def askPostID(postID): p = scribus.valueDialog( askPostIDCaption, askPostIDMessage, str(postID)) return p ############################ # HTMLparser ############################ class StripTags(HTMLParser): def __init__(self): """Initialize and reset this instance.""" self.reset() self.cursor = 0 self.initEm = 0 self.initStrong = 0 self.isCaption = False self.path = '' self.caption = '' self.credit = '' self.alt = '' def handle_starttag(self, tag, attrs): if tag == 'caption': self.isCaption = True for atr in attrs: if atr[0] == 'caption': # WP image "description" self.caption = atr[1] if tag == 'a' and self.isCaption: self.path = "" for atr in attrs: if atr[0] == "href": if atr[1].find(wp_site) == 0: self.path = atr[1] else: self.path += wp_site if atr[1][0] != "/": self.path += "/" self.path += atr[1] if tag == 'img' and self.isCaption: for atr in attrs: if atr[0] == 'title': # WP image title as photo author (credit) self.credit = atr[1] if atr[0] == 'alt': self.alt = atr[1] if (tag == 'strong') or (tag == 'b'): self.initStrong = self.cursor if (tag == 'em') or (tag == 'i'): self.initEm = self.cursor def handle_endtag(self, tag): if tag == 'caption': isCaption = False ####################################################### buildPhoto(self.path,self.caption,self.credit,self.alt) ####################################################### if (tag == 'strong') or (tag == 'b'): self.lenStrong = self.cursor - self.initStrong #scribus.deselectAll() # BUG: não está selecionando na segunda passagem scribus.selectText(self.initStrong,self.lenStrong,storyFrame) setBold() if (tag == 'em') or (tag == 'i'): self.lenEm = self.cursor - self.initEm #scribus.deselectAll() scribus.selectText(self.initEm,self.lenEm,storyFrame) setItalic() def handle_data(self, data): data = cleanText(data) # Watch for troubles self.cursor += len(unicode(data)) scribus.insertText(data,-1,storyFrame) parse = StripTags() ############################################## # SET BOLD AND ITALIC FONT # need works on mixed formats (bold italic) ############################################## def setBold(): font = scribus.getFont(storyFrame) size = scribus.getFontSize(storyFrame) font = font.replace('Regular','Bold') try: scribus.setFont(font,storyFrame) except: pass try: scribus.setFontSize(size,storyFrame) except: pass def setItalic(): font = scribus.getFont(storyFrame) size = scribus.getFontSize(storyFrame) font = font.replace('Regular','Italic') try: scribus.setFont(font,storyFrame) except: pass try: scribus.setFontSize(size,storyFrame) except: pass #################################### # BUILD PHOTO? #################################### def buildPhoto(path,caption,credit,alt): res = scribus.messageBox( buildPhotoCaption, buildPhotoMessage+'
'+path+'?', ICON_WARNING, BUTTON_OK, BUTTON_NO, BUTTON_ABORT ) if res == BUTTON_ABORT: sys.exit() if res == BUTTON_NO: return fn = path.split('/')[-1] # Get only the file name to save filename = scribus.fileDialog(saveImageCaption,imageTypes,fn,1,0,0) if filename == '': return try: urllib.urlretrieve( path, filename ) except: res = scribus.messageBox(failPhotoCaption,failPhotoMessage,ICON_WARNING,BUTTON_CANCEL) imageFrame = buildPhotoFrame(filename) captionFrame = buildCaptionFrame(imageFrame,caption) creditFrame = buildCreditFrame(imageFrame,credit) # Tricky sequence to make group ordered by 'z' order (low z order, first in group) scribus.deselectAll() scribus.selectObject(imageFrame) scribus.selectObject(captionFrame) scribus.selectObject(creditFrame) # The order of object is important to permit further script handling scribus.groupObjects() # without parameter to group remains selected group = scribus.getSelectedObject(0) scribus.textFlowMode(group,CONTOUR_LINE) def buildPhotoFrame(filename): width = 100 # millimeters height = 75 pageSize = scribus.getPageSize() x = pageSize[0] - width - gutter y = pageSize[1] - height - captionHeight imageFrame = scribus.createImage(x, y, width, height) scribus.setScaleImageToFrame(SCALETOFRAME,PROPORTIONAL,imageFrame) scribus.loadImage(filename,imageFrame) # The order of object are important to permit further script handling scribus.selectObject(imageFrame) scribus.moveSelectionToFront() flow(imageFrame, AROUND_FRAME) return imageFrame def buildCaptionFrame(imageFrame,caption): frameLeft, frameTop = scribus.getPosition(imageFrame) frameWidth, frameHeight = scribus.getSize(imageFrame) captionTop = frameTop + frameHeight captionLeft = frameLeft captionWidth = frameWidth # captionHeight = global user constant captionFrame = scribus.createText(captionLeft,captionTop,captionWidth,captionHeight) scribus.setText(caption,captionFrame) applyStyle(captionStyle,captionFrame) flow(captionFrame, AROUND_FRAME) # The order of object is important to permit further script handling scribus.selectObject(captionFrame) scribus.moveSelectionToFront() return captionFrame def buildCreditFrame(imageFrame,credit): frameLeft, frameTop = scribus.getPosition(imageFrame) frameWidth, frameHeight = scribus.getSize(imageFrame) creditTop = frameTop + frameHeight creditLeft = frameLeft + frameWidth creditWidth = frameHeight # gutter = global user constant creditFrame = scribus.createText(creditLeft,creditTop,creditWidth,gutter) scribus.setText(credit,creditFrame) applyStyle(creditStyle,creditFrame) scribus.rotateObjectAbs(90, creditFrame) # The order of object is important to permit further script handling scribus.selectObject(creditFrame) scribus.moveSelectionToFront() flow(creditFrame, AROUND_FRAME) return creditFrame ######################## # FLOW TEXT AROUND FRAME ######################## def flow(frame,mode): """Compatibiliza flow para Scribus 1.3.3 e >= 1.3.4""" try: scribus.textFlowsAroundFrame(frame, mode) # Scribus 1.3.3 except: scribus.textFlowMode(frame, mode) # Scribus >= 1.3.4 #################################### # Strip double spaces and fix quotes #################################### def cleanText(t): """Strip double spaces, hollow paragraphs, change quotes etc.""" # t = t.strip() # can't be applied inside HTMLparse loop while t.count('\t'): t = t.replace('\t','') while t.count(' '): t = t.replace(' ',' ') while t.count('\r'): # DOS/Windows end-of-paragraph style... t = t.replace('\r','\n') # changed by standard end-of-paragraph. while t.count(' \n'): t = t.replace(' \n','\n') while t.count('\n '): t = t.replace('\n ','\n') while t.count('\n\n'): t = t.replace('\n\n','\n') # Change fake quotes by true typographic quotes in portuguese tradition while t.count('\n"'): t = t.replace('\n"','\n“') while t.count(' "'): t = t.replace(' "',' “') while t.count('" '): t = t.replace('" ','” ') while t.count('",'): t = t.replace('",','”,') while t.count('".'): t = t.replace('".','”.') while t.count('."'): t = t.replace('."','”.') while t.count('.”'): t = t.replace('.”','”.') return t #################################### # Transform WordPress tags # so it can be handled by HTMLparser #################################### def reformWPtags(t): t = t.replace('[caption','') t = t.replace('[gallery','') t = t.replace('[/caption]','') return t ############################## # Get object type # Input: selected object ############################## # Output: #0: nothing selected #2: image or render frame #4: text frame #5: line #6: group or retangle #7: poligon ou poliline #8: text in line ############################## def getObjectType(objName): objType = 0 items = scribus.getPageItems() for item in items: if item[0] == objName: objType = item[1] break return objType ############################################# # Verify if selected object is group # weak: fail if there are more than one object # selected and the first object is a group ############################################# def isGroup(objeto): """Verify if object is a group. Return 0 (zero) if not group or 6 if is a group""" scribus.selectObject(objeto) name = scribus.getSelectedObject(0) type = getObjectType(name) name = scribus.getSelectedObject(0)[0:5] if (type == 6) and (scribus.selectionCount() > 1) and ((name == "Group") or (name == "Agrup")): return type else: return 0 ################### # Aply style # create style if doesn't exist ################### def applyStyle(estilo,quadro): try: scribus.setStyle(estilo, quadro) except: scribus.createParagraphStyle(estilo) scribus.setStyle(estilo, quadro) return quadro ########################### # Fetch post text and image ########################### def fetchPost(textFrame): """Fetch a blog post and format story with title, author, first paragraph, body text.""" scribus.deselectAll() scribus.selectObject(textFrame) if isGroup(textFrame): scribus.unGroupObject(textFrame) textFrame = scribus.getSelectedObject() scribus.deleteText(textFrame) post = loadWPpost(textFrame) ###################### # Handle selection ###################### def handleSelection(): """Handle selected object""" global storyFrame # If there's selected object... storyFrame = scribus.getSelectedObject(0) if storyFrame: fetchPost(storyFrame) scribus.docChanged(True) else: scribus.messageBox(generalCaption,askFrameMessage,ICON_WARNING,BUTTON_OK) ###################### # Handle document ###################### def handleDocument(): """Manipula documentos """ # If have opened document if scribus.haveDoc(): #Turn redraw off scribus.setRedraw(False) # Save user unit unit = scribus.getUnit() #Define novas unidades como "pontos tipográfico" scribus.setUnit(UNIT_MILLIMETERS) ############################# # Handle selected object ############################# handleSelection() # Restore user unit scribus.setUnit(unit) else: # If not opened doc scribus.messageBox(openDocCaption,openDocMessage,ICON_WARNING,BUTTON_OK) ####################### def main(argv): """Main entry point""" handleDocument() ####################### def main_wrapper(argv): try: scribus.statusMessage(statusMessage) scribus.progressReset() main(argv) finally: if scribus.haveDoc(): scribus.setRedraw(True) scribus.statusMessage("") scribus.progressReset() if __name__ == '__main__': main_wrapper(sys.argv)