Automate Archiving Bank Statements to Evernote in macOS

I’ve been manually archiving bank statements (PDF files) to Evernote for a while. And frankly it’s taking me a fair amount of time to do it “properly”. By that I mean:

  • One statement saved in a single note.
  • Note name should reflect which card/account the statement is from.
  • Note name should reflect which period the statement is from.
  • Note should have proper Creation Date matching the statement. It helps sorting.
  • Note should have proper tags to help searching.

So it’d take much longer than just using Evernote to clip the PDF files.

And finally I got tired of it and decided to automate this.

Demo video

When I drag the downloaded statement files into the “Dropbox” folder, they get automatically archived to Evernote and then deleted from the folder.

The solution

… is fairly straightforward.

Step 1: create a Folder Action in Automator to watch new files for a particular folder.

Step 2: for each of the new files, create a new note in an Evernote notebook with that file as the attachment.

Since this is a pretty generic step, I created a Script Library for it. See Evernote.scpt in the code below.

In my case I want all statements to be in the Finance notebook and tagged with the bank info and some extra tags to help searching. I want the name of the note to be some identification of the card and the date of the statement.

Then here’s the slightly more tricky part. AFAIK, AppleScript is not particularly good at processing strings. And because I know JavaScript better, I decided to parse the statement filename in JavaScript.

What I need is the date info in the filename and make sure the filename looks like what I’m expecting. That’s what parseFilename in 2 - Parse filenames and save to evernote.js is doing.

So why do I need 1 - Get paths and filenames from aliases.scpt at all? Well, this is embarrassing. Half way into the JavaScript I realized that I can’t use nodeJs modules like path to help me with parsing the input file paths. Manually splitting the string looks messy. Eventually I learned that getting the filename from the path is very easy so I added this extra step to convert the list of aliases to a list of descriptors that have both the path info and the name info.

I encountered a strange exception here: when I tried to save the original alias into the path property of the descriptor, Automator simply crashes.

Another caveat is, given the way of reading a property from a descriptor is propName of descriptor, the property name can’t be some pre-defined keywords, such as path. So I had to change it to "thePath".

The Automator Workflow

The code

Resizable Sidebar with (almost) Vanilla JavaScript

See the Pen Resizable Sidebar by Xingchen Hong (@Zodiase) on CodePen.0

I only used jQuery to help find proper outer-width and modify them, which could be easily replaced with a helper function. Same for lodash debouncing.

This is a very feature-lite demo but the concept should work for many scenarios, as long as there’s a container in flex mode and not wrapping content, then put the slider in that container along with the sub-containers being resized and make sure all children have proper flex settings to resize properly.

Meteor: Publish Empty Collection for Inserting Only

I’m writing a meteor app and ran into a problem where I only need a collection reference to be able to insert new documents into it. I don’t need to read any data from the collection. I think by publishing an empty collection would save the effort in synchronizing data between the server and the client which would make the app more efficient. I couldn’t find anything helpful by Googling so I came up with something myself and so far it seems to be working just fine.

Here’s how:

(Code clip removed)

I’m simply adding a filter that’s always going to get me nothing. I guess I would never have attribute undefined defined on any documents, so that would work for me.

Hope you find this helpful. 🙂

Actually you don’t even need a subscription in order to insert, as long as the server side has the same collection defined as the client side. Didn’t know that.

Updates on U-Shout

For the past days since last update, I’ve been working on solving some issues and here’s the story:

Last time I got to the point that the plugin was able to detect the page (by analyzing the url). Then the first problem I wanted to solve is ‘dynamically redirecting’ used by Youtube. I might not be naming this right but when you click on any links to redirect to another page (not opening in a new window), the page doesn’t actually reload. What actually happens is that Youtube intercepts the redirecting event, updates the address bar with the new pushState feature in html5, ‘rebuilds’ the page with Javascript and voila here you have the new page.

As a consequence, the scripts that get executed on document load will fail to work for new pages since there’s no ‘onload’ event when the new pages are simply rebuild with Javascript. Maybe Youtube is kind enough to fire another custom event when they are done with the page, but I’m not sure; I’ve been too lazy to finish reading all Youtube’s Javascript files to just find that out. But I found a workaround to that issue and that is by monitoring the “pushState” event of the window object. (It turned out that this workaround still caused many other not-yet-solved problems and you will see them in a minute.)

So I updated the plugin to re-analyze the address after every “pushState” events and make changes to the new pages accordingly. And there comes the first yet solved problem. Youtube first pushes the new state and then start rebuilding the page, which sounds alright. But if I also monitor “pushState” events and start modifying the page right after, my program will be in a race with Youtube’s and the result will just be unpredictable (and this is very very bad). The fix to that would be some ways to determine Youtube has finished modifying the page, or create new elements that Youtube won’t touch, and hide the ones Youtube works on. The later one might save me from lots of other troubles since I can avoid any further conflicts with Youtube, but that also means I need to handle everything taken care of by Youtube myself :(.

The next step was to detect what type of player is used on the page. Youtube has generally two types of player: the html5 player and the flash player (which has an AS3 version and an AS2 version). The plugin needs to do different modifications in either cases. But later I reverted this whole idea because I had a painful experience working with the html5 player (for one thing, it doesn’t even call “onYoutubePlayerReady”). I had to replace the player with an embedded version so things are consistent. So now the plugin will remove the player on the page right after loading and insert a new embedded version.

Then I hid the default control bar on the player and added a custom one so I can add my own controls without occupying extra space. The first thing I added was the ‘full-window’ toggle button because I like it the most :D.

And that’s about everything.

I’m considering re-naming my PQUEUE library to jDirector because p-queue also stands for ‘priority queue’ and even the full name ‘process queue’ doesn’t really describe the library. I think ‘Javascript Director’ fits its use more because most of the time I’m using this library, I’m organizing animations or other workflows. I’ll move files to the new project space ‘jdirector.googlecode.com’ after the next stable release of PQUEUE.

UShout Chrome Plugin ver 2014.2.6.2 update log

New testing version: 2014.2.6.2.

Changes from ver. 2013.12.9.0:

I almost removed everything that was working. You heard me right, I rolled back. I just want to re-write it so that everything is better organized and easier to understand, hopefully.

Screenshot 2014-02-07 05.23.54

Some files are re-named. Many files have been commented out. I might add some of them back but I think most likely I’ll just re-write all of them.

Now the ‘main.js’ is replaced by the ‘content_document_start.js’, which I think has a better name. 🙂

So what has been done in this brand new version? Well, very little.

But I did added something I think useful. I brought 4 new libraries of mine in to enrich the features. The PQUEUE, SETRACE and UNIQUE-IT are just small tools to help with coding, but the iNotiC could be something more interesting to the users; it’s a notification-center-like logging system!

Previously I only used console logs to give feedbacks to myself and some caring users. Then it got to the point there were just too many logs, mixed along with errors and warnings from Youtube page itself! Catching one specific log line got harder and harder. Also when Chrome is re-rendering the DOM (when there are changes in the DOM structure) and the Inspector is activated, things will slow down, if not freeze up, badly because Chrome needs to do tons of updates in the Inspector as well. Well now I put this new logging system in, it looks, at least I think, much better!

The way this iNotiC library helps is that I’m using it to prompt critical messages, and even in a good-looking way! Here are some snapshots:

Screenshot 2014-02-07 05.41.27

Screenshot 2014-02-07 05.45.22

See those red/gray blocks top right? They are prompted by ushout plugin through iNotiC. Don’t they look nice? 😀

So with that, what I’ve finished so far, that really is related with the ushout project itself, are the follows:

  • Detection of push state. Youtube is using html5 push state to change the url while NOT reloading the page, but only use ajax to load the new page. Successful detecting new states being pushed is crucial to knowing user is getting to another page and therefore the plugin needs to reset whatever changes it has done to the page and prepare to modify the new one.
  • Detection of youtubePlayerReady. It’s only safe to request Youtube Player APIs when youtubePlayerReady is detected.
  • A code structure for the outer most loop of logic of the plugin. This is done with the help of PQUEUE.

 

Plan for next?

Now that I know exactly when the user is on a page watching a video, I know when the plugin needs to make modifications to the video player. Maybe I’ll add a ‘full-window’ button first (because I really want one) but before adding any other controllers, I need to make sure I can detect all the events happening during a video such as buffering, pausing, playing, ad playing, stopping, seeking, etc.

I’ll see what I can do over this weekend.

Now I need to head to my bed!

Start working on U-Shout (again)

Well I made a proof-of-concept demo here a long time ago, but I really see the need out there and I think people will really like this, so I decided to make it into something more than a demo, a working thing hopefully.

The idea of the ‘You Shout’, or ‘UShout’ for short, is a special type of commenting service that allows you to post and see comments along with the video playing.

The whole project will be two parts. The first part is the server side program, which handles user authentication (I’m thinking of Google OAuth 2.0) and all the comment data (since I haven’t found a way to let Youtube do that :P). The second part is browser plugin for Chrome (firstly, and maybe Firefox, Safari and IE later. Yes, IE is for sure the last.) to modify Youtube pages for this service.

The code for the browser plugin is hosted on Github at the moment. I’m thinking about moving it to google code later if I see more benefits (I don’t really know what those would be, just saying).

I’ll try to keep my blogs up on the progress of this project.

Hope you like it. Thanks. 🙂