In Part 2 of this tutorial we looked at the method getNoteByGuid. This method calls getAllResourceData of our class EvernoteStore(). It has the argument resources which is returned by the function getNote of the module NoteStore.

    def getAllResourceData(self, resources):
        allResourceData = []
        if resources != None:
            for i in resources:
                fileName = i.attributes.fileName
                try:
                    if fileName.find('.') < 0: fileName = fileName+'.'+i.mime.split('/')[1]
                except: fileName = i.guid
                allResourceData.append([{'enMediaHash': i.data.bodyHash.hex(), 'fileName': fileName, 'body': i.data.body, 'size': i.data.size, 'mime': i.mime, 'width': i.width, 'height': i.height}])

        return allResourceData

resources is a list. Each list item i describes a resource (e.g. an image). The filename is stored in i.attributes.fileName. Sometimes the extension is missing in fileName. The extension is stored in i.mime (e.g.  'image/jpeg'). Sometimes we must take the guid of a resource as it's fileName.

Each resource has the field data.body (the content of the resource e.g. the binary representation of an image) and it's hash value (i.data.bodyHash.hex()). This hash value can be used to find a resource in the content of a note. Below is an example of an image reference in the note content.

<en-media hash="791054554cb482de6b29c89e09d53956" style="display: block !important; height: auto !important; max-width: 100%;" type="image/jpeg"/>

The return value of the method above, allResourceData is a list. Each list item is a dict which completely describes an image resource.

Now we are able to access a notebook by it's name and a note by it's title and we can retrieve all data of this note. What, if we want to find all notes since a specific date or all notes with some tags? As mentioned earlier this can be achieved with Evernotes powerful search grammar. To find all notes which were updated during the last 24 hours, the search string would be 'updated:day'. To find all notes with the tags 'Wine' and 'Dine' the search string would be 'tag:Wine tag:Dine' and if we want to exclude all notes with the tag 'Italy' the search string would be '-tag:Italy'. Of course we can combine everything to one search string: 'updated:day tag:Wine tag:Dine -tag:Italy'. The NoteFilter (remember our method getNoteByTitle in Part 2) would become:

search = 'updated:day tag:Wine tag:Dine -tag:Italy'
filter = NoteFilter()
filter.timeZone = self.timeZone
filter.words = search
filter.order = NoteSortOrder.UPDATED
filter.notebookGuid = self.noteBookGuid
filter.inactive = inactive

If we want to periodically check if there were changes in a notebook we use Polling. From the documentation: "Each Evernote account has a variable named updateCount that makes it easy for you to tell whether the account has been changed since the last time you looked.".  We get the updateCount with the function getSyncState() of the module NoteStore. This function also returns the currentTime together with some other data. We store the updateCount and the currentTime in a text file. Whenever we do our polling, we read from this text file: getLastUpdate(). Then we call getSyncState().

lastUpdateCount, lastUpdateTime = self.getLastUpdate()
result = self.noteStore.getSyncState()
newUpdateCount = result.updateCount
newUpdateTime = result.currentTime

If newUpdateCount > lastUpdateCount we know, that something has changed in our Evernote user account. We then check if a relevant note in a specific notebook has changed. Example: A relevant note is a note with a tag 'published' from the notebook 'Food'. Therefor we have to define a filter with the notebookGuid of the Food notebook and an update after lastUpdateTime and the tag 'published'. The search string will be: 'updated:20200704T150000Z tag:published'.

And here is the complete code for this tutorial:

from evernote.edam.type.ttypes import NoteSortOrder
from evernote.edam.notestore.ttypes import NoteFilter, NotesMetadataResultSpec
from evernote.api.client import EvernoteClient
from datetime import datetime as dt
import os

class EvernoteStore():

    def __init__(self, sandbox=False):
        if sandbox == True: authToken='your authToken for the development server'
        elif sandbox == False: authToken='your authToken for the production server'
        self.authToken = authToken
        self.sandbox = sandbox
        self.china = False
        self.noteBookName = None
        self.noteBookGuid = None
        self.client = EvernoteClient(token=self.authToken, sandbox=self.sandbox, china=self.china)
        self.userStore = self.client.get_user_store()
        self.user = self.userStore.getUser().username    # e.g. jacquesbopp
        self.noteStore = self.client.get_note_store()
        self.noteBookList = None
        self.setNoteBooksList()
        self.noteBookTags = None
        self.timeZone = 'Europe/Zurich'
        self.logDirectory = None

    def setNoteBooksList(self):
        notebooks = self.noteStore.listNotebooks()
        self.noteBookList = {'name': [],'guid':[]}
        for n in notebooks:
            self.noteBookList['name'].append(n.name)
            self.noteBookList['guid'].append(n.guid)

        return None

    def getNoteBooksList(self):
        return self.noteBookList

    def setNotebook(self, noteBookName):
        self.noteBookName = noteBookName
        self.setNoteBookGuid()

        return None

    def setNoteBookGuid(self):
        self.noteBookGuid = self.noteBookList['guid'][self.noteBookList['name'].index(self.noteBookName)]

        return None

    def getNoteBookTags(self):
        tags = self.noteStore.listTagsByNotebook(self.authToken, self.noteBookGuid)
        self.noteBookTags = {'name': [],'guid':[],'parentGuid':[]}
        for t in tags:
            self.noteBookTags['name'].append(t.name)
            self.noteBookTags['guid'].append(t.guid)
            self.noteBookTags['parentGuid'].append(t.parentGuid)

        return self.noteBookTags

    def getNoteByTitle(self, title):
        search = 'intitle:'+title
        # filter
        filter = NoteFilter()
        filter.timeZone = self.timeZone
        filter.words = search
        filter.order = NoteSortOrder.UPDATED
        filter.notebookGuid = self.noteBookGuid

        # resultspec
        resultSpec = NotesMetadataResultSpec()
        notes = self.noteStore.findNotesMetadata(self.authToken, filter, 0, 250, resultSpec)
        if len(notes.notes) > 0:
            note = self.getNoteByGuid(notes.notes[0].guid)
        else: note = {'Result': 'Error'}

        return note

    def getNoteByGuid(self, guid):
        noteE = self.getNoteData(guid)
        note = {}
        note['Result'] = 'success:'
        note['Title'] = noteE.title
        note['Guid'] = noteE.guid
        note['Notebook'] = self.noteBookList['name'][self.noteBookList['guid'].index(noteE.notebookGuid)]
        note['Created'] = enDateTimeToPythonDateTime(noteE.created)
        note['Updated'] = enDateTimeToPythonDateTime(noteE.updated)
        note['Deleted'] = enDateTimeToPythonDateTime(noteE.deleted)
        note['Content'] = self.noteStore.getNoteContent(self.authToken, noteE.guid)
        note['TagsGuid'] = noteE.tagGuids
        note['TagsName'] = self.noteStore.getNoteTagNames(self.authToken, noteE.guid)
        note['Resources'] = self.getAllResourceData(noteE.resources)

        return note

    def getNoteData(self, guid):
        # getNote is depreciated but still used because getNoteWithResultSpec does not work
        note = self.noteStore.getNote(self.authToken, guid, True, True, True, True)

        return note

    def getAllResourceData(self, resources):
        allResourceData = []
        if resources != None:
            for i in resources:
                fileName = i.attributes.fileName
                try:
                    if fileName.find('.') < 0: fileName = fileName+'.'+i.mime.split('/')[1]
                except: fileName = i.guid
                allResourceData.append([{'enMediaHash': i.data.bodyHash.hex(), 'fileName': fileName, 'body': i.data.body, 'size': i.data.size, 'mime': i.mime, 'width': i.width, 'height': i.height}])

        return allResourceData

    def getNotesBySearchString(self, search):
        notesGuid = []
        notes = []

        # filter
        filter = NoteFilter()
        filter.timeZone = self.timeZone
        filter.words = search
        filter.order = NoteSortOrder.UPDATED
        filter.notebookGuid = self.noteBookGuid
        filter.inactive = False

        # resultspec
        resultSpec = NotesMetadataResultSpec()
        # resultSpec.includeTitle = True
        # resultSpec.includeContentLength = True
        # resultSpec.includeResourcesData = True
        # resultSpec.includeCreated = True
        # resultSpec.includeUpdated = True
        # resultSpec.includeDeleted = True
        # resultSpec.includeTagGuids = True
        # resultSpec.includeAttributes = True

        # noteList
        offset = 0
        maxNotes =250

        while True:
            notes = self.noteStore.findNotesMetadata(self.authToken, filter, offset, maxNotes, resultSpec)
            for i in notes.notes: notesGuid.append(i.guid)
            if len(notesGuid) < notes.totalNotes: offset = offset+maxNotes
            else: break

        notes = []
        for i in notesGuid: notes.append(store.getNoteByGuid(i))

        return notes


    def getNotesSinceLastCheck(self, search):
        lastUpdateCount, lastUpdateTime = self.getLastUpdate()  # your log file from last check with 1 line: 45396::1598513999428 (delimiter='::', 45396=updateCount, 1598513999428=time in seconds of last check)
        result = self.noteStore.getSyncState()
        newUpdateCount = result.updateCount
        newUpdateTime = result.currentTime
        if newUpdateCount > lastUpdateCount:
            search = 'updated:'+enDateTimeToPythonDateTime(lastUpdateTime).strftime('%Y%m%dT%H%M%S')+' '+search
            notes = self.getNotesBySearchString(search)

        return notes

    def setLogDirectory(self, logDirectory):
        self.logDirectory = logDirectory
        return None

    def getLastUpdate(self):
        fileName = self.logDirectory+'evernoteLastSyncState.txt'
        if os.path.isfile(fileName):
            with open(fileName) as f: content = f.read()
            content = content.split('::')
            lastUpdateCount = int(content[0])
            lastUpdateTime = int(content[1])
        else:
            lastUpdateCount = 0
            lastUpdateTime = 0

        return lastUpdateCount, lastUpdateTime


def enDateTimeToPythonDateTime(enTime):
	try: date = dt.fromtimestamp(enTime/1000)
	except: date = None
	return date

if __name__ == '__main__':
    store = EvernoteStore()
    notebooks = store.getNoteBooksList()
    store.setNotebook('your notebook')
    tags = store.getNoteBookTags()
    note = store.getNoteByTitle('your note title')
    notes = store.getNoteBySearchString('updated:day tag:Wine tag:Dine -tag:Italy')
    store.setLogDirectory('your log directory')
    notes = store.getNotesSinceLastCheck('tag:published')

I hope this little tutorial was helpful. For any question, comments you can contact me: JacquesBopp

Back to Part 1

Back to Part 2

Sie haben sich erfolgreich bei xBopp registriert
Willkommen zurück! Ihre Anmeldung war erfolgreich.
Super! Ihre Registrierung war erfolgreich.
Gemacht! Ihre neue Email-Adresse wurde erfolgreich registriert.
Ihr Link ist abgelaufen
Super! Prüfen Sie Ihren Email-Eingang auf unseren Link zur Anmeldung.