Quick sending todos from work to home.

Recently I’ve found nice app for Windows that could help with quick adding tasks to my list at work. I haven’t wrote about my GTD system that I use in work but for now it isn’t relevant. Sometimes when I’m doing my job I suddenly get an idea or I just remember something that I should do. The main problem for me is to do not interrupt my current work because it has a great negative influence on my performance. Up to today I’ve kept a paper notebook close to me to just write any thought/task/idea and get quickly back to my previous task. It work’s well but what about more sophisticated tasks (i.e. wrote whole piece of code to check if it’s a part of my task that I should do @home). I’ve came up with simple idea – find an application that will help me add my tasks to a textfile and send it to my email account.

The application is called Launchy. I’ve added a command to Launchy that appends file when I use command ‘do’ (http://benkraal.wordpress.com/2007/05/16/launchy-append-text-to-a-file-from-anywhere/). Normally I use QuickSilver on a Mac and this feature is available from the beginning.

I have my INBOX.txt file that I use as … it’s not hard to guess – INBOX. Every task that I have to do, every little ideas that comes to me it’s simply and very quickly added to this file – using only Lanuchy and ‘do’ command. This file is used as inbox also for my work GTD system. To differ home items from the work items I use simply @home context name.

I wrote a short ruby script that parse the INBOX file and grab @home items and send it all to my private email. I use Outlook at work so it wasn’t hard to send email by Win32OLE.


require 'win32ole'

def send_email(body)
  outlook = WIN32OLE.new('Outlook.Application')
  #grab the Outlook app
  message = outlook.CreateItem(0)
  #Create item 0 - email
  message.Subject = 'Todo'
  message.Body = body
  message.To = 'your.email@mail.com'
  message.Send
end

todo = File.new('Inbox.txt',"r").readlines
#open INBOX and read tasks
File.new('Inbox.txt',"w").puts todo.reject{|el| el=~/^@home/}.to_s
#Remove processed @home tasks from INBOX
todo = todo.select{|line| line=~/^@home/}.map{|el| el.sub("@home ","")}.to_s
#remove '@home' tag from task name
send_email(todo) if todo != ""
#if there are some tasks -> send

I use todo_mail.rb script to automatically process received email.

Checking bank account with Ruby

I wrote some time ago a script that help me checking what is my account balance. I have 3 bank accounts (2 of them are free) and I want to check how much money I have or if there is my salary already. The main idea was to run this script and not giving there any password from a prompt. I didn’t want to have my bank account password written as plain text in the script so I found solution to get password from my keychain.app on Mac.


#!/usr/bin/env ruby
require 'rubygems'
require 'mechanize'
require 'osx/cocoa' #required because we use keychain
include OSX
require_framework 'Security'

#service name in keychain where I have password to my bank account
service = "Stan konta"
#account number
account = '99988877' 

# This line is left on purpose
# You can use it to add service(login&pass) to your keychain 
# SecKeychainAddGenericPassword(nil, service.length, service, account.length, account, password.length, password, nil)

#reading the password from kaychain
status, *password = SecKeychainFindGenericPassword(nil, service.length, service, account.length, account)

password_length = password.shift # getting pass length
password_data = password.shift  # and the password
password = password_data.bytestr(password_length) # converting needed

# lets start new Mechanize agent
agent = WWW::Mechanize.new
# go to bank login webpage
page = agent.get('https://www.ipko.pl')

# get the form and put login and passwd
form = page.forms.first
form.fields.with.name('client_id').value = account
form.fields.with.name('password').value = password
# submit values
page = agent.submit(form,form.buttons.first)
# and now we use simple regexp to find interesting string
# this is the part where you should discover propoer regexp on your own
sr_dostepne, saldo = page.body.to_s.scan(/[0-9\s]+,[0-9]{2}/)

# printing on screen
puts "Srodki dostepne: #{sr_dostepne}"
puts "Saldo: \t\t#{saldo}"

To find the regexp for your bank account try using irb from terminal. You can always print agent body and you will know where the interesting value is. Sometimes you need to get to go to next page after login. You can do it simply by following link on that page.

Importing notes from iPhone to iGTD

notes

I’ve recently start using iPhone as my input device. Unfortunately there was no easy way to sync my iPhone with iGTD on my mac so I thought about writing some temporary solution for that. Currently I’m using iPhone’s Notes as my inbox. I write there all the stuff I should process later. There could be more than one todo item in one note. Items are separate by endline (enter) one or more (if you like to have your list clear & readable).

Iphone’s Notes has an option to send a written note via email. I didn’t like to copy all the info from the received email and pasting it to the iGTD manually so I thought that this could be done automatically. I wrote a short Ruby script that does it for me via GMail IMAP. I am planning to develop additional application for my iPhone to read all iGTD content – for now its only this.

This simple script could be used to get info from Gmail to other GTD systems. I use iGTD at home. It has additional unix app to send any text to iGTD with special syntax (you can write from the iPhone ‘@home’ or give it specific deadline date and so on – for more info please see iGTD webpage.


require "net/imap"
user = 'username'
pass = 'password'

imap = Net::IMAP.new('imap.gmail.com','993',true)
imap.login(user,pass) # login
imap.select('INBOX') # go to inbox

# array for my tasks
tasks = []
# searching emails from me with subject "Todo"
result = imap.search(["FROM",'your.email',"SUBJECT","Todo"])
result.each do
  |email_no|
  # add tasks from email
  # split it by \r\n (endline)
  tasks += imap.fetch(email_no,'BODY[TEXT]')[0].attr["BODY[TEXT]"].split(/\r\n/)
  imap.store(email_no,"+FLAGS", [:Deleted]) # remove processed email
end

# remove footer & empty strings
tasks.reject!{ |item| item=="" or item=="Best Regards" or item =="Johny Mnemonic="} 

# run each task as parameter to sendtoigtd script
tasks.each{ |task| system("sendtoigtd",task) }
imap.disconnect

You can use it on different ways. I set cron task to start this script at the end of the day.