Home

en.mootoh.log

TwitterTimeTrack

  • 2007-10-23 (Tue)

What is this

A web service that serves your Twitter direct messages as iCalendar format. You can use it for logging your life.

How to use it

  1. Follow 2c account. As soon as follow 2c, it also immediately follows you. Then you can send direct messages to 2c.
  2. Send direct message to 2c. (example: d 2c foo bar). iCalendar file will be generated when 2 ore more direct messages.
  3. Subscribe your iCalendar url which is in form of http://deadbeaf.org/twitter2ical/ical/your_screen_name.

Screenshots

TwitterTimeTrack via Google Calendar TwitterTimeTrack via iCal

Restrictions

Everything is on memory, so I cannot hold so much messages. Precisely, max users are 100, total messages every user can hold is latest 128 messages. If users exceed 100, it will shift oldest user’s entry.

Background

I read a book Leverage Time Management (in Japanese), and decided to log how I use my lifetime. I noticed Twitter would be nice for it, so made this.

user_timeline_to_ical

What is this ?

A simple Ruby script that generates iCalendar format from Twitter user_timeline.

Download

user_timeline_to_ical.rb

Requirements

following gems installed:

  • json
  • icalendar

How to use

simply type

ruby user_timeline_to_ical.rb [your_screen_name]

to print out recent 20 events in iCalendar format to stdout.

Redirect its output to a file, then import it with iCal or Google Calendar.

Screenshot

from iCal: Twitter to iCalendar-01

from Google Calendar: Twitter to iCalendar-02

Future …

I’m developing a web service that serves iCalendar feed (by sending direct message to tracking bot). You will subscribe its URL to see your past behaviors at some time.

Code

Try it !

#
# create iCalendar from recent 20 user_timeline.
#
# usage
#   ruby user_timeline_to_ical.rb [username] > some.ics
#
require 'rubygems'
require 'json'
require 'icalendar'
require 'uri'
require 'open-uri'
require 'kconv'
require 'nkf'
require 'logger'
 
KCODE = 'u'
 
# XXX:
#   quick fix to avoid charset crash
module Icalendar
  class Component < Icalendar::Base
    def print_properties
      s = ""
 
      @properties.each do |key,val| 
        # Take out underscore for property names that conflicted
        # with built-in words.
        if key =~ /ip_.*/
          key = key[3..-1]
        end
 
        # Property name
        unless multiline_property?(key)
           prelude = "#{key.gsub(/_/, '-').upcase}" +
 
           # Possible parameters
           print_parameters(val) 
 
           # Property value
           value = ":#{val.to_ical}" 
           escaped = prelude + value.gsub("\\", "\\\\").gsub("\n", "\\n").gsub(",", "\\,").gsub(";", "\\;")
           #escaped = value
           #s << escaped.slice!(0, MAX_LINE_LENGTH) << "\r\n " while escaped.size > MAX_LINE_LENGTH # XXX : quick fix to avoid charset crash
           s << escaped << "\r\n"
           s.gsub!(/ *$/, '')
         else 
           prelude = "#{key.gsub(/_/, '-').upcase}" 
            val.each do |v| 
               params = print_parameters(v)
               value = ":#{v.to_ical}"
               escaped = prelude + params + value.gsub("\\", "\\\\").gsub("\n", "\\n").gsub(",", "\\,").gsub(";", "\\;")
               s << escaped.slice!(0, MAX_LINE_LENGTH) << "\r\n " while escaped.size > MAX_LINE_LENGTH
               s << escaped << "\r\n"
               s.gsub!(/ *$/, '')
            end
         end
      end
      s
    end
  end
end
 
class UserTimeLine
  attr_accessor :id, :since
  URL = 'http://twitter.com/statuses/user_timeline/'
 
  def initialize(id)
    @id = id
    #@log = Logger.new('debug.log')
  end
 
  def get(url)
    JSON.parse(open(url).readlines.join).sort { |a, b| a['id'] <=> b['id'] }
  end
 
  def url(*arg)
    url = URL + @id + '.json'
    return url if arg.empty?
 
    hash = arg[0]
    args = {}
 
    args['page'] = hash[:page] if hash[:page]
    if hash[:since]
      if String == hash[:since].class 
        args['since'] = URI.escape(hash[:since].split.join('+'))
      else # should be Number
        args['since_id'] = hash[:since]
      end
    end
    arg = args.collect { |k, v| [k, v].join('=') }.join('&')
 
    url + '?' + arg
  end
 
  def to_ical
    msgs = get(url).collect {|x| [x['text'], x['created_at']]}
    cal = Icalendar::Calendar.new
 
    (msgs.size-1).times do |i|
      cal.event do
        dtstart  DateTime.parse(msgs[i][1]).to_ical(true)
        dtend    DateTime.parse(msgs[i+1][1]).to_ical(true)
        summary  msgs[i][0]
      end
    end
 
    cal.to_ical
  end
end
 
 
utl = UserTimeLine.new(ARGV.shift)
print NKF.nkf('-w -Lw', utl.to_ical)

SocketReaderPatch

SocketReaderPatch

What is SocketReaderPatch ?

A Coustom Quartz Composer Patch that recieves strings from TCP Socket.

Download

Install

Copy SocketReaderPatch.plugin into /Library/Graphics/Patch .

How to use

Open QuartzComposer, find SocketReader from the Patch Library list (type “Socket” in Search in Libraries field to search it) .

Then drag SocketReader into right pane, and play it. SocketReader listens port number 12345 in default. Make some client application and write UTF-8 strings into the socket, and Quartz Composer will show that strings.

Example

Simple Example

ScreenCast !

Note

  • Very buggy. If two or more sockets are connected, CPU usage will be so high.
  • To change the port number, edit port_ variable in SocketReaderPatch.m.

Reference

I used Quartz Composer Custom Patch Xcode template from fdiv.net:Xcode Template for Custom Quartz Composer Patches. (Thanks!)

In order to play with socket in Cocoa, O’Reilly Network::mac devcenter::Networking in Cocoa was pretty helpful.

Motivation

I came up to an idea that IRC messages flow beautifully by using QuartzComposer, in RubyKaigi2007 . To push dynamic text into QuartzComposer, it seemed to be only RSS feed out there.

License

CC : Attribution-NonCommercial-ShareAlike, because above Xcode template claims that license.

Contact

Any feedbacks are welcome, mail me.

Home

Feeds

Return to page top