A Clojure library to access the Evernote API.
A library that wraps the official Evernote Java API . As of writing it implements the following:
- OAuth authentication (using Scribe Java)
- Basic read/write capabilities, using an OAuth access token, or developer token.
- ENML to HTML translation
Include the following dependency in your project.clj
file:
:dependencies [[clojurenote "0.4.0"]]
- An Evernote developer API key (from here)
- You should start working against the Sandbox, rather than Production, environment. You can get a Sandbox account here.
- A basic knowledge of the fundamentals of the Evernote API is probably worth having.
For OAuth authentication you need to have a web application. There is a sample app here in the clojurenote-demo
tree. Check out that directory and use it as the basis of your implementation.
Note that you only need a web application for authentication. Once you've got your access token you can access the API from any type of app.
Take a look at auth.clj
file. There are a few options for configuring the demo. The easiest way is to hard code your API key and secret into the config
function. Alternatively you can use environment variables / leiningen config as explained in auth.clj
Once you've got your config ready run the app as follows:
$ lein ring server
(This assumes you have Leiningen installed)
This should open up a browser at https://localhost:3000
. Press the 'Login to Evernote' button to initiate the login process. Eventually you should get back to a page giving your
access token and notestore URL. Copy these 2 things down since you'll need them next.
The usage API is split in two. Most of what you need is based off the Evernote NoteStore. You can create a NoteStore with clojurenote.note/create-note-store
and call any method using interop. Alternatively there are convenience functions that are the bulk of clojurenotes.notes
.
Most API functions take a 'user' map as their first argument. The simplest way of setting this is to use the map you got from 'obtain-access-token' in the authentication phase.
Alternatively the map must consist of the following entries:
:access-token
- The long access token string from the authentication phase
Then either of the following:
:notestore-url
- The user-specific notestore url (again, supplied during authentication):notestore
- An actual NoteStore object, typically created by callingclojurenote.stores/create-note-store
If you are using a developer token then :access-token
will be your developer token, and you should specify a :notestore
entry with the returned value from calling clojurenote.notes/create-note-store-with-developer-token
There is a very simple example of using the notes API in the clojurenote-demo.use
namespace. There are also several examples in the clojurenote.notes-expectations
tests namespace.
Otherwise here are some repl examples, including use of the clojurenote.enml
namespace described in the next section :
user=> (use 'clojurenote.notes)
nil
user=> (def en-user {:access-token "My-Access-Token" :notestore-url "https://sandbox.evernote.com/shard/s1/notestore"})
#'user/en-user
user=> (list-notebooks en-user)
#<ArrayList [Notebook(guid:...)]>
user=> (create-notebook en-user "TestNotebook")
#<Notebook Notebook(guid:...)>
user=> (find-notebook-by-name en-user "TestNotebook")
#<Notebook Notebook(guid:...)>
user=> (map (comp :title bean (partial get-note en-user) :guid bean) (basic-notes-for-notebook en-user "my-notebook-guid"))
("Note 1 Title" "Note 2 Title")
user=> (use 'clojurenote.enml)
nil
user=> (write-note en-user "my-notebook-guid" "First note" (create-enml-document "My content"))
#<Note Note(guid:...)>
user=> (get-note en-user "my-note-guid")
#<Note Note(guid:...)>
user=> (-> (get-note en-user "my-note-guid") (note->html))
"<div>\nMy content\n</div>\n"
Various functions for working with Note Resources are also provided. Read the documentation in the source for more.
- Objects returned have not had
bean
called on them due to possible performace constraints within the client application, but that's typically something you'll want to do first if you don't have such constraints. - The content for any notes you create must be a valid ENML document, and the content of returned notes will be ENML documents. See the next section for more on this subject.
The content field of an Evernote Note is an ENML document. ENML is XHTML with a few extra Evernote specific tags, and some other tags removed. For more information see here.
The clojurenote.enml
namespace provides the note->html
(which takes a whole Note) and enml->html
(which takes a specified pre-retrived ENML document) functions to map to regular HTML. They do 2 things:
- Remove the XML headers
- Translate the
<en-*
tags to html equivalents.
The default behavior of the translations are:
- replace
<en-note>
with<div>
, keeping all attributes - replace
<en-media>
,<en-crypt>
and<en-todo>
with plain spans
The translation behavior can configured by specifying optional name / fn pairs when calling either of the *->html
functions, where the names are the same as those in default-en-tag-fns
. Each function takes an xml node, as returned by a parsing of the ENML with clojure.xml
.
Typically you'll want to at least do something more useful for <en-media>
tags, based on the hash
attribute. A simple example translating <en-media>
to <img>
tags is given in en-media->simple-img-fn
. An example of converting an <en-note>
tag to an actual HTML document is given in en-note->html-document
.
The namespace also contains the create-enml-document
function to create the basic structure of an ENML document. It will only create the header and footer though - the remaining content must already be valid ENML.
Look at the clojurenote.enml-expectations
namespace for examples.
As mentioned above most of what you need from the Evernote API is based off of the NoteStore (and clojurenote.notes
), however there is also some useful stuff in the UserStore, and this is reflected in the clojurenote.users
namespace.
All of the functions in clojurenote.users
require a service argument, which should be one of :production
, :sandbox
, or :yinxiang
, depending on which Evernote service you are accessing. Some also take an access-token
argument, which is the long :access-token
string returned that is part of the map returned by clojurenote.auth/obtain-access-token
, or your developer token if you're using developer tokens.
Here are some examples:
user=> (use 'clojurenote.users)
nil
user=> (get-user-details :sandbox (:access-token full-access-token))
#<User User(id:...)>
user=> (get-notestore-url :sandbox (:access-token full-access-token))
"https://sandbox.evernote.com/shard/s1/notestore"