def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception, e: logging.error("Error: %s : %s", func.__name__, str(e)) if not hasattr(e, 'errorCode'): out.failureMessage("Sorry, operation has failed!!!.") tools.exitErr() errorCode = int(e.errorCode) # auth-token error, re-auth if errorCode == 9: storage = Storage() storage.removeUser() GeekNote() return func(*args, **kwargs) elif errorCode == 3: out.failureMessage("Sorry, you do not have permissions " "to do this operation.") # Rate limited # Patched because otherwise if you get rate limited you still keep # hammering the server on scripts elif errorCode == 19: print("\nRate Limit Hit: Please wait %s seconds before continuing" % str(e.rateLimitDuration)) tools.exitErr() else: return False tools.exitErr()
def _searchNote(self, note): note = tools.strip(note) # load search result result = self.getStorage().getSearch() if result and tools.checkIsInt(note) and 1 <= int(note) <= len(result.notes): note = result.notes[int(note) - 1] else: request = self._createSearchRequest(search=note) logging.debug("Search notes: %s" % request) result = self.getEvernote().findNotes(request, 20) logging.debug("Search notes result: %s" % str(result)) if result.totalNotes == 0: out.failureMessage("Notes have not been found.") return tools.exitErr() elif result.totalNotes == 1 or self.selectFirstOnUpdate: note = result.notes[0] else: logging.debug("Choose notes: %s" % str(result.notes)) note = out.SelectSearchResult(result.notes) logging.debug("Selected note: %s" % str(note)) return note
def find(self, search=None, tags=None, notebooks=None, date=None, exact_entry=None, content_search=None, with_url=None, count=None, ignore_completed=None, reminders_only=None,): request = self._createSearchRequest(search, tags, notebooks, date, exact_entry, content_search, ignore_completed, reminders_only) if not count: count = 20 else: count = int(count) logging.debug("Search count: %s", count) createFilter = True if search == "*" else False result = self.getEvernote().findNotes(request, count, createFilter) if result.totalNotes == 0: out.failureMessage("Notes have not been found.") return tools.exitErr() # save search result # print result self.getStorage().setSearch(result) out.SearchResult(result.notes, request, showUrl=with_url)
def _createSearchRequest(self, search=None, tags=None, notebooks=None, date=None, exact_entry=None, content_search=None): request = "" if notebooks: for notebook in tools.strip(notebooks.split(',')): if notebook.startswith('-'): request += '-notebook:"%s" ' % tools.strip(notebook[1:]) else: request += 'notebook:"%s" ' % tools.strip(notebook) if tags: for tag in tools.strip(tags.split(',')): if tag.startswith('-'): request += '-tag:"%s" ' % tag[1:] else: request += 'tag:"%s" ' % tag if date: date = tools.strip(date.split('-')) try: dateStruct = time.strptime(date[0] + " 00:00:00", "%d.%m.%Y %H:%M:%S") request += 'created:%s ' % time.strftime("%Y%m%d", time.localtime(time.mktime(dateStruct))) if len(date) == 2: dateStruct = time.strptime(date[1] + " 00:00:00", "%d.%m.%Y %H:%M:%S") request += '-created:%s ' % time.strftime("%Y%m%d", time.localtime(time.mktime(dateStruct) + 60 * 60 * 24)) except ValueError, e: out.failureMessage('Incorrect date format in --date attribute. ' 'Format: %s' % time.strftime("%d.%m.%Y", time.strptime('19991231', "%Y%m%d"))) return tools.exitErr()
def textToENML(content, raise_ex=False, format='markdown'): """ Create an ENML format of note. """ if not isinstance(content, str): content = "" try: content = unicode(content, "utf-8") # add 2 space before new line in paragraph for cteating br tags content = re.sub(r'([^\r\n])([\r\n])([^\r\n])', r'\1 \n\3', content) if format=='markdown': contentHTML = markdown.markdown(content).encode("utf-8") # remove all new-lines characters in html contentHTML = re.sub(r'\n', r'', contentHTML) else: contentHTML = HTMLEscape(content) return wrapENML(contentHTML) except: if raise_ex: raise Exception("Error while parsing text to html." " Content must be an UTF-8 encode.") logging.error("Error while parsing text to html. " "Content must be an UTF-8 encode.") out.failureMessage("Error while parsing text to html. " "Content must be an UTF-8 encode.") return tools.exit()
def make_resource(filename): try: mtype = mimetypes.guess_type(filename)[0] if mtype.split('/')[0] == "text": rmode = "r" else: rmode = "rb" with open(filename, rmode) as f: """ file exists """ resource = Types.Resource() resource.data = Types.Data() data = f.read() md5 = hashlib.md5() md5.update(data) resource.data.bodyHash = md5.hexdigest() resource.data.body = data resource.data.size = len(data) resource.mime = mtype resource.attributes = Types.ResourceAttributes() resource.attributes.fileName = os.path.basename(filename) return resource except IOError: msg = "The file '%s' does not exist." % filename out.failureMessage(msg) raise IOError(msg)
def textToENML(content, raise_ex=False, format='markdown'): """ Create an ENML format of note. """ if not isinstance(content, str): content = "" try: content = unicode(content, "utf-8") # add 2 space before new line in paragraph for creating br tags content = re.sub(r'([^\r\n])([\r\n])([^\r\n])', r'\1 \n\3', content) if format=='markdown': contentHTML = markdown.markdown(content).encode("utf-8") # Non-Pretty HTML output contentHTML = str(BeautifulSoup(contentHTML)) else: contentHTML = Editor.HTMLEscape(content) return Editor.wrapENML(contentHTML) except: if raise_ex: raise Exception("Error while parsing text to html." " Content must be an UTF-8 encode.") logging.error("Error while parsing text to html. " "Content must be an UTF-8 encode.") out.failureMessage("Error while parsing text to html. " "Content must be an UTF-8 encode.") return tools.exit()
def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception, e: logging.error("Error: %s : %s", func.__name__, str(e)) if not hasattr(e, 'errorCode'): out.failureMessage("Sorry, operation has failed!!!.") tools.exit() errorCode = int(e.errorCode) # auth-token error, re-auth if errorCode == 9: storage = Storage() storage.removeUser() GeekNote() return func(*args, **kwargs) elif errorCode == 3: out.failureMessage("Sorry, you do not have permissions to do this operation.") else: return False tools.exit()
def edit( self, note, title=None, content=None, tag=None, created=None, notebook=None, resource=None, reminder=None, url=None, raw=None, ): self.connectToEvernote() note = self._searchNote(note) inputData = self._parseInput(title, content, tag, created, notebook, resource, note, reminder, url) if inputData["content"] == config.EDITOR_OPEN: result = self._editWithEditorInThread(inputData, note, raw=raw) else: out.preloader.setMessage("Saving note...") result = bool(self.getEvernote().updateNote(guid=note.guid, **inputData)) if result: out.successMessage("Note successfully saved.") else: out.failureMessage("Error: could not save note.") return tools.exitErr()
def create( self, title, content=None, tag=None, created=None, notebook=None, resource=None, reminder=None, url=None, raw=None, ): self.connectToEvernote() # Optional Content. content = content or " " inputData = self._parseInput(title, content, tag, created, notebook, resource, None, reminder, url) if inputData["content"] == config.EDITOR_OPEN: result = self._editWithEditorInThread(inputData, raw=raw) else: out.preloader.setMessage("Creating note...") result = bool(self.getEvernote().createNote(**inputData)) if result: out.successMessage("Note successfully created.") else: out.failureMessage("Error: could not create note.") return tools.exitErr()
def _parseInput(self, title=None, content=None, tags=None, notebook=None, resources=[], note=None, reminder=None): result = { "title": title, "content": content, "tags": tags, "notebook": notebook, "resources": resources, "reminder": reminder, } result = tools.strip(result) # if get note without params if note and title is None and content is None and tags is None and notebook is None: content = config.EDITOR_OPEN if title is None and note: result['title'] = note.title if content: if content != config.EDITOR_OPEN: if isinstance(content, str) and os.path.isfile(content): logging.debug("Load content from the file") content = open(content, "r").read() logging.debug("Convert content") content = Editor.textToENML(content) result['content'] = content if tags: result['tags'] = tools.strip(tags.split(',')) if notebook: notepadGuid = Notebooks().getNoteGUID(notebook) if notepadGuid is None: newNotepad = Notebooks().create(notebook) notepadGuid = newNotepad.guid result['notebook'] = notepadGuid logging.debug("Search notebook") if reminder: then = config.REMINDER_SHORTCUTS.get(reminder) if then: now = int(round(time.time() * 1000)) result['reminder'] = now + then elif reminder not in [config.REMINDER_NONE, config.REMINDER_DONE, config.REMINDER_DELETE]: reminder = tools.strip(reminder.split('-')) try: dateStruct = time.strptime(reminder[0] + " " + reminder[1] + ":00", config.DEF_DATE_AND_TIME_FORMAT) reminderTime = int(round(time.mktime(dateStruct) * 1000)) result['reminder'] = reminderTime except (ValueError, IndexError): out.failureMessage('Incorrect date format in --reminder attribute. ' 'Format: %s' % time.strftime(config.DEF_DATE_FORMAT, time.strptime('199912311422', "%Y%m%d%H%M"))) return tools.exitErr() return result
def createNote( self, title, content, tags=None, created=None, notebook=None, resources=None, reminder=None, url=None ): note = Types.Note() note.title = title try: note.content = content.encode("utf-8") except UnicodeDecodeError: note.content = content if tags: note.tagNames = tags note.created = created if notebook: note.notebookGuid = notebook if resources: """ make EverNote API resources """ note.resources = map(make_resource, resources) """ add to content """ resource_nodes = "" for resource in note.resources: resource_nodes += '<en-media type="%s" hash="%s" />' % (resource.mime, resource.data.bodyHash) note.content = note.content.replace("</en-note>", resource_nodes + "</en-note>") # Allow creating a completed reminder (for task tracking purposes), # skip reminder creation steps if we have a DELETE if reminder and reminder != config.REMINDER_DELETE: if not note.attributes: # in case no attributes available note.attributes = Types.NoteAttributes() now = int(round(time.time() * 1000)) if reminder == config.REMINDER_NONE: note.attributes.reminderOrder = now elif reminder == config.REMINDER_DONE: note.attributes.reminderOrder = now note.attributes.reminderDoneTime = now else: # we have an actual reminder time stamp if reminder > now: # future reminder only note.attributes.reminderOrder = now note.attributes.reminderTime = reminder else: out.failureMessage("Error: reminder must be in the future.") tools.exitErr() if url: if note.attributes is None: note.attributes = Types.NoteAttributes() note.attributes.sourceURL = url logging.debug("New note : %s", note) return self.getNoteStore().createNote(self.authToken, note)
def user(self, full=None): if not self.getEvernote().checkAuth(): out.failureMessage("You are not logged in.") return tools.exitErr() if full: info = self.getEvernote().getUserInfo() else: info = self.getStorage().getUserInfo() out.showUser(info, full)
def login(self): if self.getEvernote().checkAuth(): out.failureMessage("You have already logged in.") return tools.exitErr() if self.getEvernote().auth(): out.successMessage("You have successfully logged in.") else: out.failureMessage("Login error.") return tools.exitErr()
def edit(self, tagname, title): tag = self._searchTag(tagname) out.preloader.setMessage("Updating tag...") result = self.getEvernote().updateTag(guid=tag.guid, name=title) if result: out.successMessage("Tag has been successfully updated.") else: out.failureMessage("Error while the updating the tag.") return tools.exitErr()
def find( self, search=None, tag=None, notebook=None, date=None, exact_entry=None, content_search=None, with_url=None, with_tags=None, with_notebook=None, count=None, ignore_completed=None, reminders_only=None, guid=None, ): request = self._createSearchRequest( search, tag, notebook, date, exact_entry, content_search, ignore_completed, reminders_only ) if not count: count = 20 else: count = int(count) logging.debug("Search count: %s", count) createFilter = True if search == "*" else False result = self.getEvernote().findNotes(request, count, createFilter) if result.totalNotes == 0: out.failureMessage("Notes have not been found.") return tools.exitErr() # save search result # print result self.getStorage().setSearch(result) for note in result.notes: self.getStorage().setNote(note) if with_notebook: noteStore = self.getEvernote().getNoteStore() notebookNameFromGuid = dict() for note in result.notes: if note.notebookGuid not in notebookNameFromGuid: notebookNameFromGuid[note.notebookGuid] = noteStore.getNotebook( self.getEvernote().authToken, note.notebookGuid ).name note.notebookName = notebookNameFromGuid[note.notebookGuid] out.SearchResult( result.notes, request, showUrl=with_url, showTags=with_tags, showNotebook=with_notebook, showGUID=guid )
def edit(self, notebook, title): notebook = self._searchNotebook(notebook) out.preloader.setMessage("Updating notebook...") result = self.getEvernote().updateNotebook(guid=notebook.guid, name=title) if result: out.successMessage("Notebook has been successfully updated.") else: out.failureMessage("Error while the updating the notebook.") return tools.exit()
def create(self, title, stack=None): self.connectToEvernote() out.preloader.setMessage("Creating notebook...") result = self.getEvernote().createNotebook(name=title, stack=stack) if result: out.successMessage("Notebook successfully created.") else: out.failureMessage("Error: could not create notebook.") return tools.exitErr() return result
def create(self, title): self.connectToEvernote() out.preloader.setMessage("Creating notebook...") result = self.getEvernote().createNotebook(name=title) if result: out.successMessage("Notebook has been successfully created.") else: out.failureMessage("Error while the process of creating the notebook.") return tools.exit() return result
def create(self, title): self.connectToEvertone() out.preloader.setMessage("Creating tag...") result = self.getEvernote().createTag(name=title) if result: out.successMessage("Tag has been successfully created.") else: out.failureMessage("Error while the process of creating the tag.") return tools.exitErr() return result
def create(self, title): self.connectToEvernote() out.preloader.setMessage("Creating tag...") result = self.getEvernote().createTag(name=title) if result: out.successMessage("Tag successfully created.") else: out.failureMessage("Error: tag could not be created.") return tools.exitErr() return result
def remove(self, tagname, force=None): tag = self._searchTag(tagname) if not force and not out.confirm('Are you sure you want to delete this tag: "%s"?' % tag.name): return tools.exit() out.preloader.setMessage("Deleting tag...") result = self.getEvernote().removeTag(guid=tag.guid) if result: out.successMessage("Tag has been successfully removed.") else: out.failureMessage("Error while removing the tag.")
def remove(self, notebook, force=None): notebook = self._searchNotebook(notebook) if not force and not out.confirm('Are you sure you want to delete this notebook: "%s"?' % notebook.name): return tools.exit() out.preloader.setMessage("Deleting notebook...") result = self.getEvernote().removeNotebook(guid=notebook.guid) if result: out.successMessage("Notebook has been successfully removed.") else: out.failureMessage("Error while removing the notebook.")
def create(self, title, content, tags=None, notebook=None): self.connectToEvertone() inputData = self._parceInput(title, content, tags, notebook) out.preloader.setMessage("Creating note...") result = self.getEvernote().createNote(**inputData) if result: out.successMessage("Note has been successfully created.") else: out.failureMessage("Error while creating the note.")
def logout(self, force=None): if not self.getEvernote().checkAuth(): out.failureMessage("You have already logged out.") return tools.exitErr() if not force and not out.confirm('Are you sure you want to logout?'): return tools.exit() result = self.getEvernote().removeUser() if result: out.successMessage("You have successfully logged out.") else: out.failureMessage("Logout error.") return tools.exitErr()
def remove(self, tagname, force=None): tag = self._searchTag(tagname) if not force and not out.confirm('Are you sure you want to ' 'delete this tag: "%s"?' % tag.name): return tools.exit() out.preloader.setMessage("Deleting tag...") result = self.getEvernote().removeTag(guid=tag.guid) if result: out.successMessage("Tag has been successfully removed.") else: out.failureMessage("Error while removing the tag.")
def remove(self, notebook, force=None): notebook = self._searchNotebook(notebook) if not force and not out.confirm('Are you sure you want to delete' ' this notebook: "%s"?' % notebook.name): return tools.exit() out.preloader.setMessage("Deleting notebook...") result = self.getEvernote().removeNotebook(guid=notebook.guid) if result: out.successMessage("Notebook has been successfully removed.") else: out.failureMessage("Error while removing the notebook.")
def edit(self, note, title=None, content=None, tags=None, notebook=None): self.connectToEvertone() note = self._searchNote(note) inputData = self._parceInput(title, content, tags, notebook, note) out.preloader.setMessage("Saving note...") result = self.getEvernote().updateNote(guid=note.guid, **inputData) if result: out.successMessage("Note has been successfully saved.") else: out.failureMessage("Error while saving the note.")
def textToENML(content, raise_ex=False, format='markdown'): """ Create an ENML format of note. """ if not isinstance(content, str): content = "" try: content = unicode(content, "utf-8") # add 2 space before new line in paragraph for creating br tags content = re.sub(r'([^\r\n])([\r\n])([^\r\n])', r'\1 \n\3', content) if format == 'markdown': storage = Storage() extras = storage.getUserprop('markdown2_extras') #contentHTML = markdown.markdown(content).encode("utf-8") contentHTML = markdown.markdown(content, extras=extras).encode("utf-8") soup = BeautifulSoup(contentHTML, 'html.parser') Editor.checklistInSoupToENML(soup) # Non-Pretty HTML output contentHTML = str(soup) # # For the 'pre' format, simply wrap the content with a 'pre' tag. Do # perform any parsing/mutation. # elif format == 'pre': contentHTML = u''.join( ('<pre>', content, '</pre>')).encode("utf-8") else: contentHTML = Editor.HTMLEscape(content) contentHTML = contentHTML.replace( '[x]', '<en-todo checked="true"></en-todo>') contentHTML = contentHTML.replace('[ ]', '<en-todo></en-todo>') return Editor.wrapENML(contentHTML) except: import traceback traceback.print_exc() if raise_ex: raise Exception("Error while parsing text to html." " Content must be an UTF-8 encode.") logging.error("Error while parsing text to html. " "Content must be an UTF-8 encode.") out.failureMessage("Error while parsing text to html. " "Content must be an UTF-8 encode.") return tools.exitErr()
def createNote(self, title, content, tags=None, created=None, notebook=None, resources=None, reminder=None): note = Types.Note() note.title = title try: note.content = content.encode('utf-8') except UnicodeDecodeError: note.content = content if tags: note.tagNames = tags note.created = created if notebook: note.notebookGuid = notebook if resources: """ make EverNote API resources """ note.resources = map(make_resource, resources) """ add to content """ resource_nodes = "" for resource in note.resources: resource_nodes += '<en-media type="%s" hash="%s" />' % (resource.mime, resource.data.bodyHash) note.content = note.content.replace("</en-note>", resource_nodes + "</en-note>") # Allow creating a completed reminder (for task tracking purposes), # skip reminder creation steps if we have a DELETE if reminder and reminder != config.REMINDER_DELETE: now = int(round(time.time() * 1000)) note.attributes = Types.NoteAttributes() if reminder == config.REMINDER_NONE: note.attributes.reminderOrder = now elif reminder == config.REMINDER_DONE: note.attributes.reminderOrder = now note.attributes.reminderDoneTime = now else: # we have an actual reminder time stamp if reminder > now: # future reminder only note.attributes.reminderOrder = now note.attributes.reminderTime = reminder else: out.failureMessage("Error: reminder must be in the future.") tools.exitErr() logging.debug("New note : %s", note) return self.getNoteStore().createNote(self.authToken, note)
def remove(self, note, force=None): self.connectToEvertone() note = self._searchNote(note) if not force and not out.confirm('Are you sure you want to delete this note: "%s"?' % note.title): return tools.exit() out.preloader.setMessage("Deleting note...") result = self.getEvernote().removeNote(note.guid) if result: out.successMessage("Note has been successful deleted.") else: out.failureMessage("Error while deleting the note.")
def _getTimeFromDate(self, date): dateStruct = None for fmt in config.DEF_DATE_FORMAT, config.DEF_DATE_AND_TIME_FORMAT: try: dateStruct = time.strptime(date, fmt) except ValueError: pass if not dateStruct: out.failureMessage( 'Error while parsing date: "%s" is in an ' "incorrect format. Dates should\nbe specified as " '"yyyy-mm-dd" or "yyyy-mm-dd HH:MM" strings.' % date ) return tools.exitErr() return int(round(time.mktime(dateStruct) * 1000))
def textToENML(content, raise_ex=False, format='markdown'): """ Create an ENML format of note. TODO: add media support """ if not isinstance(content, str): content = "" try: content = unicode(content, "utf-8") # add 2 space before new line in paragraph for creating br tags content = re.sub(r'([^\r\n])([\r\n])([^\r\n])', r'\1 \n\3', content) if format == 'markdown': contentHTML = markdown.markdown(content).encode("utf-8") # Non-Pretty HTML output contentHTML = str(BeautifulSoup(contentHTML, 'html.parser')) elif format == 'html': # Html to ENML http://dev.evernote.com/doc/articles/enml.php ATTR_2_REMOVE = ["id" , "class" #, "on*" , "accesskey" , "data" , "dynsrc" , "tabindex" ]; soup = BeautifulSoup(content, 'html.parser') for tag in soup.findAll(): if hasattr(tag, 'attrs'): map(lambda x: tag.attrs.pop(x, None), \ [k for k in tag.attrs.keys() \ if k in ATTR_2_REMOVE \ or k.find('on') == 0]) contentHTML = str(soup) else: contentHTML = Editor.HTMLEscape(content) return Editor.wrapENML(contentHTML) except: if raise_ex: raise Exception("Error while parsing text to html." " Content must be an UTF-8 encode.") logging.error("Error while parsing text to html. " "Content must be an UTF-8 encode.") out.failureMessage("Error while parsing text to html. " "Content must be an UTF-8 encode.") return tools.exit()
def settings(self, editor=None, extras=None, note_ext=None): storage = self.getStorage() if editor: if editor == '#GET#': out.successMessage("Current editor is: %s" % getEditor(storage)) else: storage.setUserprop('editor', editor) out.successMessage("Changes saved.") if extras: if extras == '#GET#': out.successMessage("Current markdown2 extras is : %s" % getExtras(storage)) else: storage.setUserprop('markdown2_extras', extras.split(',')) out.successMessage("Changes saved.") if note_ext: if note_ext == '#GET#': out.successMessage("Default note extension is: %s" % getNoteExt(storage)) else: if len(note_ext.split(',')) == 2: storage.setUserprop('note_ext', note_ext.replace(" ","")) out.successMessage("Changes saved.") else: out.failureMessage("Error in note extension, format is '.markdown, .org'") if all([not editor, not extras, not note_ext]): editor = getEditor(storage) extras = getExtras(storage) note_ext = getNoteExt(storage) settings = ('Geeknote', '*' * 30, 'Version: %s' % __version__, 'App dir: %s' % config.APP_DIR, 'Error log: %s' % config.ERROR_LOG, 'Current editor: %s' % editor, 'Markdown2 Extras: %s' % (extras if extras is None else ','.join(extras)), 'Note extension: %s' % note_ext) user_settings = storage.getUserprops() if user_settings: user = user_settings[1]['info'] settings += ('*' * 30, 'Username: %s' % user.username, 'Id: %s' % user.id, 'Email: %s' % user.email) out.printLine('\n'.join(settings))
def settings(self, editor=None, extras=None, note_ext=None): storage = self.getStorage() if editor: if editor == '#GET#': out.successMessage("Current editor is: %s" % getEditor(storage)) else: storage.setUserprop('editor', editor) out.successMessage("Changes saved.") if extras: if extras == '#GET#': out.successMessage("Current markdown2 extras is : %s" % getExtras(storage)) else: storage.setUserprop('markdown2_extras', extras.split(',')) out.successMessage("Changes saved.") if note_ext: if note_ext == '#GET#': out.successMessage("Default note extension is: %s" % getNoteExt(storage)) else: if len(note_ext.split(',')) == 2: storage.setUserprop('note_ext', note_ext.replace(" ", "")) out.successMessage("Changes saved.") else: out.failureMessage( "Error in note extension, format is '.markdown, .org'") if all([not editor, not extras, not note_ext]): editor = getEditor(storage) extras = getExtras(storage) note_ext = getNoteExt(storage) settings = ('Geeknote', '*' * 30, 'Version: %s' % __version__, 'App dir: %s' % config.APP_DIR, 'Error log: %s' % config.ERROR_LOG, 'Current editor: %s' % editor, 'Markdown2 Extras: %s' % (extras if extras is None else ','.join(extras)), 'Note extension: %s' % note_ext) user_settings = storage.getUserprops() if user_settings: user = user_settings[1]['info'] settings += ('*' * 30, 'Username: %s' % user.username, 'Id: %s' % user.id, 'Email: %s' % user.email) out.printLine('\n'.join(settings))
def find( self, search=None, tags=None, notebooks=None, date=None, exact_entry=None, content_search=None, with_url=None, count=None, ): request = self._createSearchRequest(search, tags, notebooks, date, exact_entry, content_search) if not count: count = 20 else: count = int(count) logging.debug("Search count: %s", count) createFilter = True if search == "*" else False result = self.getEvernote().findNotes(request, count, createFilter) # Reduces the count by the amount of notes already retrieved update_count = lambda c: max(c - len(result.notes), 0) count = update_count(count) # Evernote api will only return so many notes in one go. Checks for more # notes to come whilst obeying count rules while ((result.totalNotes != len(result.notes)) and count != 0): offset = len(result.notes) result.notes += self.getEvernote().findNotes( request, count, createFilter, offset).notes count = update_count(count) if result.totalNotes == 0: out.failureMessage("Notes have not been found.") return tools.exitErr() # save search result # print result self.getStorage().setSearch(result) out.SearchResult(result.notes, request, showUrl=with_url)
def edit(self, note, title=None, content=None, tag=None, created=None, notebook=None, resource=None, reminder=None, raw=None): self.connectToEvernote() note = self._searchNote(note) inputData = self._parseInput(title, content, tag, created, notebook, resource, note, reminder=reminder) if inputData['content'] == config.EDITOR_OPEN: result = self._editWithEditorInThread(inputData, note, raw=raw) else: out.preloader.setMessage("Saving note...") result = bool(self.getEvernote().updateNote(guid=note.guid, **inputData)) if result: out.successMessage("Note successfully saved.") else: out.failureMessage("Error: could not save note.") return tools.exitErr()
def edit(self, note, title=None, content=None, tags=None, notebook=None, resource=None): self.connectToEvertone() note = self._searchNote(note) inputData = self._parseInput(title, content, tags, notebook, resource, note) if inputData['content'] == config.EDITOR_OPEN: result = self._editWithEditorInThread(inputData, note) else: out.preloader.setMessage("Saving note...") result = bool(self.getEvernote().updateNote(guid=note.guid, **inputData)) if result: out.successMessage("Note has been successfully saved.") else: out.failureMessage("Error while saving the note.")
def find(self, search=None, tag=None, notebooks=None, date=None, exact_entry=None, content_search=None, with_url=None, with_tags=None, with_notebook=None, count=None, ignore_completed=None, reminders_only=None, guid=None): request = self._createSearchRequest(search, tag, notebooks, date, exact_entry, content_search, ignore_completed, reminders_only) if not count: count = 20 else: count = int(count) logging.debug("Search count: %s", count) createFilter = True if search == "*" else False result = self.getEvernote().findNotes(request, count, createFilter) if result.totalNotes == 0: out.failureMessage("Notes have not been found.") return tools.exitErr() # save search result # print result self.getStorage().setSearch(result) for note in result.notes: self.getStorage().setNote(note) out.SearchResult(result.notes, request, showUrl=with_url, showTags=with_tags, showNotebook=with_notebook, showGUID=guid)
def modifyArgsByStdinStream(): content = sys.stdin.read() content = tools.stdinEncode(content) if not content: out.failureMessage("Input stream is empty.") return tools.exit() title = ' '.join(content.split(' ', 5)[:-1]) title = re.sub(r'(\r\n|\r|\n)', r' ', title) if not title: out.failureMessage("Error while crating title of note from stream.") return tools.exit() elif len(title) > 50: title = title[0:50] + '...' ARGS = {'title': title, 'content': content} return ('create', ARGS)
def create(self, title, content=None, tag=None, created=None, notebook=None, resource=None, reminder=None, raw=None): self.connectToEvernote() # Optional Content. content = content or " " inputData = self._parseInput(title, content, tag, created, notebook, resource, reminder=reminder) if inputData['content'] == config.EDITOR_OPEN: result = self._editWithEditorInThread(inputData, raw=raw) else: out.preloader.setMessage("Creating note...") result = bool(self.getEvernote().createNote(**inputData)) if result: out.successMessage("Note successfully created.") else: out.failureMessage("Error: could not create note.") return tools.exitErr()
def _createSearchRequest(self, search=None, tags=None, notebooks=None, date=None, exact_entry=None, content_search=None): request = "" if notebooks: for notebook in tools.strip(notebooks.split(',')): if notebook.startswith('-'): request += '-notebook:"%s" ' % tools.strip(notebook[1:]) else: request += 'notebook:"%s" ' % tools.strip(notebook) if tags: for tag in tools.strip(tags.split(',')): if tag.startswith('-'): request += '-tag:"%s" ' % tag[1:] else: request += 'tag:"%s" ' % tag if date: date = tools.strip(date.split('-')) try: dateStruct = time.strptime(date[0] + " 00:00:00", "%d.%m.%Y %H:%M:%S") request += 'created:%s ' % time.strftime( "%Y%m%d", time.localtime(time.mktime(dateStruct))) if len(date) == 2: dateStruct = time.strptime(date[1] + " 00:00:00", "%d.%m.%Y %H:%M:%S") request += '-created:%s ' % time.strftime( "%Y%m%d", time.localtime(time.mktime(dateStruct) + 60 * 60 * 24)) except ValueError, e: out.failureMessage( 'Incorrect date format in --date attribute. Format: %s' % time.strftime("%d.%m.%Y", time.strptime('19991231', "%Y%m%d"))) return tools.exit()
def create(self, title, content=None, tags=None, notebook=None, resource=None): self.connectToEvertone() # Optional Content. content = content or " " inputData = self._parseInput(title, content, tags, notebook, resource) if inputData['content'] == config.EDITOR_OPEN: result = self._editWithEditorInThread(inputData) else: out.preloader.setMessage("Creating note...") result = bool(self.getEvernote().createNote(**inputData)) if result: out.successMessage("Note has been successfully created.") else: out.failureMessage("Error while creating the note.")
def remove(self, note, force=None): self.connectToEvernote() note = self._searchNote(note) if note: out.preloader.setMessage("Loading note...") self.getEvernote().loadNoteContent(note) out.showNote(note, self.getEvernote().getUserInfo().id, self.getEvernote().getUserInfo().shardId) if not force and not out.confirm('Are you sure you want to ' 'delete this note: "%s"?' % note.title): return tools.exit() out.preloader.setMessage("Deleting note...") result = self.getEvernote().removeNote(note.guid) if result: out.successMessage("Note successfully deleted.") else: out.failureMessage("Error: could not delete note.") return tools.exitErr()
def backup(self, notebook, outputFormat='console'): logging.debug("Backup to %s" % str(outputFormat)) notebook = self._searchNotebook(notebook) notes = self.getEvernote().loadNotes(notebook) if outputFormat == 'file': if not os.path.exists(notebook.name): os.mkdir(notebook.name) else: out.failureMessage("Folder %s already exist" % notebook.name) for n in notes: note = self.getEvernote().getNote(n.guid) if outputFormat == 'console': out.showNote(note) out.printLine('======================') if outputFormat == 'file': with opened(notebook.name + os.sep + note.title, "w") as f: with stdout_redirected(f): out.showNote(note)
def textToENML(content, raise_ex=False): """ Create an ENML format of note. """ if not isinstance(content, str): content = "" try: content = unicode(content,"utf-8") # add 2 space before new line in paragraph for cteating br tags content = re.sub(r'([^\r\n])([\r\n])([^\r\n])', r'\1 \n\3', content) contentHTML = markdown.markdown(content).encode("utf-8") # remove all new-lines characters in html contentHTML = re.sub(r'\n', r'', contentHTML) return wrapENML(contentHTML) except: if raise_ex: raise Exception("Error while parsing text to html. Content must be an UTF-8 encode.") logging.error("Error while parsing text to html. Content must be an UTF-8 encode.") out.failureMessage("Error while parsing text to html. Content must be an UTF-8 encode.") return tools.exit()
def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception, e: logging.error("Error: %s : %s", func.__name__, str(e)) if not hasattr(e, 'errorCode'): out.failureMessage("Operation failed!") traceback.print_exc() tools.exitErr() errorCode = int(e.errorCode) # auth-token error, re-auth if errorCode == 9: storage = Storage() storage.removeUser() GeekNote() return func(*args, **kwargs) elif errorCode == 3: out.failureMessage("Sorry, you are not authorized " "to perform this operation.") # Rate limited # Patched because otherwise if you get rate limited you still keep # hammering the server on scripts elif errorCode == 19: print( "\nRate Limit Hit: Please wait %s seconds before continuing" % str(e.rateLimitDuration)) tools.exitErr() else: print e return False tools.exitErr()
def _finalizeEditor(self, editor, result): if result: editor.deleteTempfile() else: out.failureMessage("Edited note could not be saved, so it remains in %s" % editor.tempfile)
def dedup(self, search=None, tag=None, notebook=None, date=None, exact_entry=None, content_search=None, with_url=None, count=None): request = self._createSearchRequest(search, tag, notebook, date, exact_entry, content_search) if not count: count = 20 else: count = int(count) logging.debug("Search count: %s", count) createFilter = True if search == "*" else False notes = [] evernote = self.getEvernote() stillDownloadingResults = True while stillDownloadingResults: offset = len(notes) result = evernote.findNotes(request, count, createFilter, offset) notes += result.notes total = result.totalNotes limit = min(total, count) stillDownloadingResults = len(notes) < total and len(notes) < count out.printLine("Downloaded metadata for " + str(len(result.notes)) + " notes (" + str(len(notes)) + "/" + str(limit) + " of " + str(count) + ")") if total == 0: out.failureMessage("Notes have not been found.") return tools.exitErr() notes_dict = {} for note in notes: noteId = note.title + ":" + note.contentHash if noteId in notes_dict: notes_dict[noteId].append(note) out.printLine("found dup! \"" + note.title + "\" with guid " + note.guid + ", duplicated " + len(notes_dict[noteId])) else: notes_dict[noteId] = [note] out.printLine("new note \"" + note.title + "\" with guid " + note.guid) all_dups = [ dups for id, dups in notes_dict.iteritems() if len(dups) > 1 ] # list of lists total_dups = sum(map(len, all_dups)) # count total removed_total = 0 for dup_group in all_dups: group_size = len(dup_group) out.printLine("Deleting " + group_size + " notes titled \"" + dup_group[0].title + "\"") for note in dup_group: removed_total += 1 out.printLine("Deleting \"" + note.title + "\" created " + out.printDate(note.created) + " with guid " + note.guid + " (" + str(removed_total) + "/" + str(total_dups) + ")") evernote.removeNote(note.guid) out.printLine("removed " + removed_total + "duplicates")
def _createSearchRequest(self, search=None, tags=None, notebook=None, date=None, exact_entry=None, content_search=None, ignore_completed=None, reminders_only=None): request = "" def _formatExpression(label, value): """Create an expression like label:value, attending to negation and quotes """ expression = "" # if negated, prepend that to the expression before labe, not value if value.startswith('-'): expression += '-' value = value[1:] value = tools.strip(value) # values with spaces must be quoted if ' ' in value: value = '"%s"' % value expression += '%s:%s ' % (label, value) return expression if notebook: request += _formatExpression('notebook', notebook) if tags: for tag in tags: request += _formatExpression('tag', tag) if date: date = tools.strip(re.split(config.DEF_DATE_RANGE_DELIMITER, date)) # Timestamps used by the evernote service will always be in UTC, # per https://discussion.evernote.com/topic/18792-get-timestamp-in-local-time-zone/ # (user.timezone refers only to the UI and has no effect on the API) # Here we assume the user is specifying localized time, so we use _getTimeFromDate to # give us the UTC timestamp try: request += 'created:%s ' % time.strftime( "%Y%m%dT%H%M00Z", time.gmtime(self._getTimeFromDate(date[0]) / 1000)) if len(date) == 2: request += '-created:%s ' % time.strftime( "%Y%m%dT%H%M00Z", time.gmtime( self._getTimeFromDate(date[1]) / 1000 + 60 * 60 * 24)) except ValueError: out.failureMessage( 'Incorrect date format (%s) in --date attribute. ' 'Format: %s' % (date, time.strftime(config.DEF_DATE_FORMAT, time.strptime('20151231', "%Y%m%d")))) return tools.exitErr() if search: search = tools.strip(search) if exact_entry or self.findExactOnUpdate: search = '"%s"' % search if content_search: request += "%s" % search else: request += "intitle:%s" % search if reminders_only: request += ' reminderOrder:* ' if ignore_completed: request += ' -reminderDoneTime:* ' logging.debug("Search request: %s", request) return request
def updateNote(self, guid, title=None, content=None, tags=None, created=None, notebook=None, resources=None, reminder=None, url=None): note = Types.Note() note.guid = guid if title: note.title = title if content: try: note.content = content.encode('utf-8') except UnicodeDecodeError: note.content = content if tags: note.tagNames = tags note.created = created if notebook: note.notebookGuid = notebook if resources: """ make EverNote API resources """ note.resources = map(make_resource, resources) """ add to content """ resource_nodes = "" for resource in note.resources: resource_nodes += '<en-media type="%s" hash="%s" />' % ( resource.mime, resource.data.bodyHash) if not note.content: note.content = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note></en-note>' note.content = note.content.replace("</en-note>", resource_nodes + "</en-note>") if reminder: if not note.attributes: # in case no attributes available note.attributes = Types.NoteAttributes() now = int(round(time.time() * 1000)) if reminder == config.REMINDER_NONE: note.attributes.reminderDoneTime = None note.attributes.reminderTime = None if not note.attributes.reminderOrder: # new reminder note.attributes.reminderOrder = now elif reminder == config.REMINDER_DONE: note.attributes.reminderDoneTime = now if not note.attributes.reminderOrder: # catch adding DONE to non-reminder note.attributes.reminderOrder = now note.attributes.reminderTime = None elif reminder == config.REMINDER_DELETE: note.attributes.reminderOrder = None note.attributes.reminderTime = None note.attributes.reminderDoneTime = None else: # we have an actual reminder timestamp if reminder > now: # future reminder only note.attributes.reminderTime = reminder note.attributes.reminderDoneTime = None if not note.attributes.reminderOrder: # catch adding time to non-reminder note.attributes.reminderOrder = now else: out.failureMessage( "Sorry, reminder must be in the future.") tools.exitErr() if url: if not note.attributes: # in case no attributes available note.attributes = Types.NoteAttributes() note.attributes.sourceURL = url logging.debug("Update note : %s", note) self.getNoteStore().updateNote(self.authToken, note) return True
def _parseInput(self, title=None, content=None, tags=[], created=None, notebook=None, resources=[], note=None, reminder=None, url=None): result = { "title": title, "content": content, "tags": tags, "created": created, "notebook": notebook, "resources": resources, "reminder": reminder, "url": url, } result = tools.strip(result) # if get note without params if (note and title is None and content is None and tags is None and created is None and notebook is None and resources is None and reminder is None and url is None): content = config.EDITOR_OPEN if title is None and note: result['title'] = note.title if content: if content != config.EDITOR_OPEN: if isinstance(content, str) and os.path.isfile(content): logging.debug("Load content from the file") content = open(content, "r").read() logging.debug("Convert content") content = Editor.textToENML(content) result['content'] = content if created: try: result['created'] = self._getTimeFromDate(created) except ValueError: out.failureMessage( "Incorrect date format (%s) in --created attribute. 'Format: '%s' or '%s'" % (created, time.strftime(config.DEF_DATE_FORMAT, time.strptime('20151231', "%Y%m%d")), time.strftime( config.DEF_DATE_AND_TIME_FORMAT, time.strptime('201512311430', "%Y%m%d%H%M")))) return tools.exitErr() if notebook: notebookGuid = Notebooks()._getNotebookGUID(notebook) if notebookGuid is None: newNotebook = Notebooks().create(notebook) notebookGuid = newNotebook.guid result['notebook'] = notebookGuid logging.debug("Search notebook") if reminder: then = config.REMINDER_SHORTCUTS.get(reminder) if then: now = int(round(time.time() * 1000)) result['reminder'] = now + then elif reminder not in [ config.REMINDER_NONE, config.REMINDER_DONE, config.REMINDER_DELETE ]: try: result['reminder'] = self._getTimeFromDate(reminder) except ValueError: out.failureMessage( "Incorrect date format (%s) in --reminder attribute. 'Format: '%s' or '%s'" % (reminder, time.strftime(config.DEF_DATE_FORMAT, time.strptime('20151231', "%Y%m%d")), time.strftime( config.DEF_DATE_AND_TIME_FORMAT, time.strptime('201512311430', "%Y%m%d%H%M")))) return tools.exitErr() if url is None and note: if note.attributes is not None: result['url'] = note.attributes.sourceURL return result
def textToENML(content, raise_ex=False, format='markdown'): """ Create an ENML format of note. """ if not isinstance(content, str): content = "" try: content = unicode(content, "utf-8") # add 2 space before new line in paragraph for creating br tags # content = re.sub(r'([^\r\n])([\r\n])([^\r\n])', r'\1 \n\3', content) content = re.sub(r'\r\n', '\n', content) if format == 'markdown': storage = Storage() extras = storage.getUserprop('markdown2_extras') content = Editor.HTMLEscapeTag(content) contentHTML = markdown.markdown(content, extras=extras) soup = BeautifulSoup(contentHTML, 'html.parser') Editor.checklistInSoupToENML(soup) # Non-Pretty HTML output contentHTML = str(soup) elif format == 'pre': # # For the 'pre' format, simply wrap the content with a 'pre' tag. Do # perform any parsing/mutation. # contentHTML = u''.join( ('<pre>', content, '</pre>')).encode("utf-8") elif format == 'html': # Html to ENML http://dev.evernote.com/doc/articles/enml.php ATTR_2_REMOVE = [ "id", "class", # "on*", "accesskey", "data", "dynsrc", "tabindex" ] soup = BeautifulSoup(content, 'html.parser') for tag in soup.findAll(): if hasattr(tag, 'attrs'): map(lambda x: tag.attrs.pop(x, None), [ k for k in tag.attrs.keys() if k in ATTR_2_REMOVE or k.find('on') == 0 ]) contentHTML = str(soup) else: contentHTML = Editor.HTMLEscape(content) tmpstr = '' for l in contentHTML.split('\n'): if l == '': tmpstr = tmpstr + u'<div><br/></div>' else: tmpstr = tmpstr + u'<div>' + l + u'</div>' contentHTML = tmpstr.encode("utf-8") contentHTML = contentHTML.replace( '[x]', '<en-todo checked="true"></en-todo>') contentHTML = contentHTML.replace('[ ]', '<en-todo></en-todo>') return Editor.wrapENML(contentHTML) except: import traceback traceback.print_exc() if raise_ex: raise Exception("Error while parsing text to html." " Content must be an UTF-8 encode.") logging.error("Error while parsing text to html. " "Content must be an UTF-8 encode.") out.failureMessage("Error while parsing text to html. " "Content must be an UTF-8 encode.") return tools.exitErr()
def textToENML(content, raise_ex=False, format='markdown', rawmd=False): """ Transform formatted text to ENML """ if not isinstance(content, str): content = "" try: content = unicode(content, "utf-8") content = re.sub(r'\r\n', '\n', content) if format == 'pre': # For the 'pre' format, simply wrap the content with a 'pre' tag. # Do not perform any further parsing/mutation. contentHTML = u''.join( ('<pre>', content, '</pre>')).encode("utf-8") elif format == 'markdown': # Markdown format https://daringfireball.net/projects/markdown/basics storage = Storage() extras = storage.getUserprop('markdown2_extras') if not rawmd: content = Editor.HTMLEscapeTag(content) contentHTML = markdown.markdown(content, extras=extras) soup = BeautifulSoup(contentHTML, 'html.parser') Editor.checklistInSoupToENML(soup) contentHTML = str(soup) elif format == 'html': # Html to ENML http://dev.evernote.com/doc/articles/enml.php soup = BeautifulSoup(content, 'html.parser') ATTR_2_REMOVE = [ "id", "class", # "on*", "accesskey", "data", "dynsrc", "tabindex" ] for tag in soup.findAll(): if hasattr(tag, 'attrs'): map(lambda x: tag.attrs.pop(x, None), [ k for k in tag.attrs.keys() if k in ATTR_2_REMOVE or k.find('on') == 0 ]) contentHTML = str(soup) else: # Plain text format contentHTML = Editor.HTMLEscape(content) tmpstr = '' for l in contentHTML.split('\n'): if l == '': tmpstr = tmpstr + u'<div><br/></div>' else: tmpstr = tmpstr + u'<div>' + l + u'</div>' contentHTML = tmpstr.encode("utf-8") contentHTML = contentHTML.replace( '[x]', '<en-todo checked="true"></en-todo>') contentHTML = contentHTML.replace('[ ]', '<en-todo></en-todo>') return Editor.wrapENML(contentHTML) except: import traceback traceback.print_exc() if raise_ex: raise Exception("Error while parsing text to html.") logging.error("Error while parsing text to html.") out.failureMessage("Error while parsing text to html.") return tools.exitErr()
def textToENML(content, raise_ex=False, format="markdown", rawmd=False): """ Transform formatted text to ENML """ if not isinstance(content, str): content = "" try: content = unicode(content, "utf-8") # add 2 space before new line in paragraph for creating br tags content = re.sub(r"([^\r\n])([\r\n])([^\r\n])", r"\1 \n\3", content) # content = re.sub(r'\r\n', '\n', content) if format == "pre": # For the 'pre' format, simply wrap the content with a 'pre' tag. # Do not perform any further parsing/mutation. contentHTML = u"".join( ("<pre>", content, "</pre>")).encode("utf-8") elif format == "markdown": # Markdown format https://daringfireball.net/projects/markdown/basics extras = None if not rawmd: storage = Storage() extras = storage.getUserprop("markdown2_extras") content = Editor.HTMLEscapeTag(content) contentHTML = markdown.markdown(content, extras=extras) soup = BeautifulSoup(contentHTML, "html.parser") Editor.checklistInSoupToENML(soup) contentHTML = str(soup) elif format == "html": # Html to ENML http://dev.evernote.com/doc/articles/enml.php soup = BeautifulSoup(content, "html.parser") ATTR_2_REMOVE = [ "id", "class", # "on*", "accesskey", "data", "dynsrc", "tabindex", ] for tag in soup.findAll(): if hasattr(tag, "attrs"): map( lambda x: tag.attrs.pop(x, None), [ k for k in tag.attrs.keys() if k in ATTR_2_REMOVE or k.find("on") == 0 ], ) contentHTML = str(soup) else: # Plain text format contentHTML = Editor.HTMLEscape(content) tmpstr = "" for l in contentHTML.split("\n"): if l == "": tmpstr = tmpstr + u"<div><br/></div>" else: tmpstr = tmpstr + u"<div>" + l + u"</div>" contentHTML = tmpstr.encode("utf-8") contentHTML = contentHTML.replace( "[x]", '<en-todo checked="true"></en-todo>') contentHTML = contentHTML.replace("[ ]", "<en-todo></en-todo>") return Editor.wrapENML(contentHTML) except: import traceback traceback.print_exc() if raise_ex: raise Exception("Error while parsing text to html.") logging.error("Error while parsing text to html.") out.failureMessage("Error while parsing text to html.") return tools.exitErr()