'Evernoting' from the command line
Older Article
This article was published 13 years ago. Some information may be outdated or no longer applicable.
I won’t argue whether Evernote is good or useless. For a long time I didn’t get the hype. Then I found a genuine use for it: a single place to dump all my scripts and code snippets that had been scattered across random text files on my laptop.
I was writing some Puppet scripts inside a virtual machine and I wanted to save them to Evernote directly from the terminal. No copy-pasting. Just a simple command line interface that lets me push an entry straight into my notes.
I found the official Evernote PHP-SDK and an example that made the whole thing much easier. I extended it and made it (shall we say) “command line compatible”. The example script uses EDAM (no, not the Dutch cheese): Evernote Data Access Management, a protocol for exchanging data with the Evernote service. Under the hood, EDAM runs on Thrift, a binary communication protocol originally developed by Facebook and now hosted by the Apache Software Foundation. Thrift allows the definition and creation of services for a large number of languages.
Before we go any further, grab an Authorisation Token from either https://sandbox.evernote.com/api/DeveloperToken.action or https://www.evernote.com/api/DeveloperToken.action (depending on whether you want to save notes to a sandbox environment or your real notebook). If you’ve already got a token, keep it handy. We’ll need it shortly.
The script (which I’ve intuitively named ‘note.php’) has two run modes: ‘cli’ and ‘file’. The ‘cli’ mode sends whatever you type in the command line to Evernote. The ‘file’ mode reads the entire contents of a file and saves it as a note. Both modes accept standard HTML tags, so you can use to highlight something if you like.
The script takes 3 arguments:
--mode: either '_cli_' or '_file_'
--subject: the title of the note
--text: the text **or** file content to save as a note.
php note.php cli "Test Note" "This is a test note. It accepts **HTML** tags as well."
php note.php file "Another test" /path/to/your-file.log
And here’s the command to execute from your command line: Which results in the following note created in the Evernote web interface:
The first section of the code is similar to the original example provided by Evernote. The only difference is a help function I’ve added that describes the script’s functionality. Let’s look at what it actually does.
use EDAM\Types\Data, EDAM\Types\Note;
use EDAM\Error\EDAMUserException, EDAM\Error\EDAMErrorCode;
use Evernote\Client;
require_once 'autoload.php';
require_once 'Evernote/Client.php';
require_once 'packages/Errors/Errors_types.php';
require_once 'packages/Types/Types_types.php';
require_once 'packages/Limits/Limits_constants.php';
function help() {
echo "\nThis is a command line PHP script with the following options:
Usage:
" . basename(__FILE__) . " cli|file title \"text\"|\"/path/to/file\"
title: Title of note
cli: to be followed by \"text\", e.g:
" . basename(__FILE__) . " cli \"Note title\" \"Add to note\"
file: must be followed by a path, e.g.:
" . basename(__FILE__) . " file \"Another title\" \"/home/user/notes.txt\"
Both the cli and file options accept HTML tags as parameters, e.g.:
" . basename(__FILE__) . " cli \"My Title\" \"I can accept **HTML tags**\"\n
";
}
The real work happens in a custom function. The highlighted line is where you drop in your developer access token. Once authentication is done, we create a new Client object and a new Note object, set the required parameters (title, content, bearing in mind that Evernote uses their own markup language, ENML), and call createNote() to save:
<?php
function addNote($title, $content) {
$authToken = "";
$client = new Client(array('token' => $authToken));
$noteStore = $client->getNoteStore();
$note = new Note();
$note->title = $title;
// The content of an Evernote note is represented using Evernote Markup Language
// (ENML). The full ENML specification can be found in the Evernote API Overview
// at http://dev.evernote.com/documentation/cloud/chapters/ENML.php
$note->content =
'<?xml version="1.0" encoding="UTF-8"?>' .
'<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">' .
'<en-note>' . nl2br($content) . '<br/></en-note>';
// When note titles are user-generated, it's important to validate them
$len = strlen($note->title);
$min = $GLOBALS['EDAM_Limits_Limits_CONSTANTS']['EDAM_NOTE_TITLE_LEN_MIN'];
$max = $GLOBALS['EDAM_Limits_Limits_CONSTANTS']['EDAM_NOTE_TITLE_LEN_MAX'];
$pattern = '#' . $GLOBALS['EDAM_Limits_Limits_CONSTANTS']['EDAM_NOTE_TITLE_REGEX'] . '#'; // Add PCRE delimiters
if ($len < $min || $len > $max || !preg_match($pattern, $note->title)) {
print "\nInvalid note title: " . $note->title . '\n\n';
exit(1);
}
$createdNote = $noteStore->createNote($note);
print "Successfully created a new note: " . $note->title . " (GUID: " . $createdNote->guid . ")\n";
}
?>
I’ve also added some error checking and logic to prevent anyone with clumsy fingers from accidentally saving a file path as the note text instead of reading the file:
<?php
if ($argc != 4 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) {
help();
exit();
} else {
$mode = isset($argv[1]) ? $argv[1] : undef;
$title = isset($argv[2]) ? $argv[2] : undef;
$content = isset($argv[3]) ? $argv[3] : undef;
if (!isset($mode) || !isset($title) || !isset($title)) {
help();
}
if ($mode == "cli") {
addNote($title, $content);
}
elseif ($mode == "file") {
//parse file
if (!file_exists($content)) {
echo "The file defined cannot be found - make sure you entered the right file (" . $content . ") and that you're using the right parameter ('file').";
help();
exit();
} else {
$content = file_get_contents($content);
addnote($title, $content);
}
}
else {
help();
exit();
}
}
?>
That’s it. If you want to try this out, you’ll need all the Evernote libraries. Feel free to grab my code (including all the required files) from GitHub. Happy Evernoting!