Friday, August 27, 2010

The end of the beginning

I will continue posting blog on lance.x10.mx.

Wednesday, September 23, 2009

Deploy dabr on byethost

You may know that dabr requires the PHP module mcrypt to run, but byethost does not support it. so I modify the /dabr/common/user.php to bypass it:
function _user_encrypt_cookie() {
  $plain_text = $GLOBALS['user']['username'] . ':' . $GLOBALS['user']['password'] . ':' . $GLOBALS['user']['type'];
  /*
  $td = mcrypt_module_open('blowfish', '', 'cfb', '');
  $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
  mcrypt_generic_init($td, _user_encryption_key(), $iv);
  $crypt_text = mcrypt_generic($td, $plain_text);
  mcrypt_generic_deinit($td);
  return base64_encode($iv.$crypt_text);
  */
  return base64_encode($plain_text);
}
  
function _user_decrypt_cookie($crypt_text) {
  $plain_text = base64_decode($crypt_text);
  /*
  $td = mcrypt_module_open('blowfish', '', 'cfb', '');
  $ivsize = mcrypt_enc_get_iv_size($td);
  $iv = substr($crypt_text, 0, $ivsize);
  $crypt_text = substr($crypt_text, $ivsize);
  mcrypt_generic_init($td, _user_encryption_key(), $iv);
  $plain_text = mdecrypt_generic($td, $crypt_text);
  mcrypt_generic_deinit($td);
  
  list($GLOBALS['user']['username'], $GLOBALS['user']['password'], $GLOBALS['user']['type']) = explode(':', $plain_text);
  */
  list($GLOBALS['user']['username'], $GLOBALS['user']['password'], $GLOBALS['user']['type']) = explode(':', $plain_text);
}
That's it, very easy. But the risk is that your Twitter user name and password are saved as cookies in plain text.

Tuesday, September 15, 2009

Export your Twitter timeline to Google Calendar

This is the Python code to do the thing. I use Jython 2.5 and gdata 2.0.2. If you are running it behind proxy, you can set the environment as below:
set https_proxy=https://https_proxy
set http_proxy=http://http_proxy
set proxy-username=proxy-username
set proxy-password=proxy-password
And here is the source code:
try:
  from xml.etree import ElementTree
except ImportError:
  from elementtree import ElementTree
import gdata.calendar.service
import gdata.service
import atom.service
import gdata.calendar
import atom
import time
import datetime

gUsr = 'Gmail address'
gPwd = 'Gmail password'

tUsr   = 'Twitter user name'

# Depends on your tweets, 
# it should be 200/tweets
tPage  = 5
tCount = 200

# After run the script, 
# you can get the last id from the result
last_id = ''

twitURL = 'http://www.twitter.com/'

months_choices = {}
for i in range(1,13):
  months_choices[datetime.date(2009, i, 1).strftime('%b')] = i

class gCalendar:
  '''
  Refer to \gdata-2.0.2\samples\calendar\calendarExample.py
  '''

  def __init__(self, email, password):

    self.cal_client = gdata.calendar.service.CalendarService()
    self.cal_client.email = email
    self.cal_client.password = password
    self.cal_client.source = 'Twitter sync'
    self.cal_client.ProgrammaticLogin()

  def InsertEvent(self, title='title',
      content='content', where='where',
      start_time=None, end_time=None, recurrence_data=None):

    event = gdata.calendar.CalendarEventEntry()
    event.title = atom.Title(text=title)
    event.content = atom.Content(text=content)
    event.where.append(gdata.calendar.Where(value_string=where))

    if recurrence_data is not None:
      # Set a recurring event
      event.recurrence = gdata.calendar.Recurrence(text=recurrence_data)
    else:
      if start_time is None:
        # Use current time for the start_time and have the event last 1 hour
        start_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime())
        end_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z',
            time.gmtime(time.time() + 1))
      event.when.append(gdata.calendar.When(start_time=start_time,
          end_time=end_time))

    new_event = self.cal_client.InsertEvent(event,
        '/calendar/feeds/default/private/full')

    return new_event

def userTimeline(tusr, count=5, page=1, since=1):

  statuses_user_timeline = twitURL + \
    'statuses/user_timeline.xml?screen_name=%s&count=%s&page=%s&since_id=%s'

  c = atom.http.ProxiedHttpClient()

  r = c.request('GET', statuses_user_timeline % (tusr, count, page, since))

  return r.read()

def feedCal(gService, xml):
  global last_id
  
  tree = ElementTree.fromstring(xml)

  status = tree.getiterator('status')

  for s in status:
    id = s.find('id').text
    c = s.find('text').text
    t = s.find('created_at').text
    t1 = t.split()
    t2 = [int(i) for i in t1[3].split(':')]
    st = datetime.datetime(int(t1[5]), int(months_choices[t1[1]]), int(t1[2]),
      t2[0], t2[1], t2[2])

    td = datetime.timedelta(seconds=1)
    et = st + td

    gService.InsertEvent(c, 'ID: %s' % id, 'twitter',
      st.strftime('%Y-%m-%dT%H:%M:%S.000Z'),
      et.strftime('%Y-%m-%dT%H:%M:%S.000Z'))

    # Get the first id as the last id
    if last_id < id: last_id = id

# Start here
def main():
  global last_id
  
  gCal = gCalendar(gUsr, gPwd)

  if last_id:
    feedCal(gCal, userTimeline(tUsr, tCount, 1, last_id))
  else:
    for i in range(1,tPage):
      feedCal(gCal, userTimeline(tUsr, tCount, str(i)))

  print '  Last id is', last_id

if __name__ == '__main__':
  print time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()), 'start'
  main()
  print time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()), 'complete'

Monday, August 17, 2009

Using Google Voice

Thanks to these two articles google.org.cn and wodingdong's blog, I finally got my GV number - (586) 330-9093, which is very similar to the number I'm using. After that, I tried to send sms to China(me, China mobile), Australia(haven't gotten feedback) and HongKong(three, 3G). Next, I think I will forward the GV to gizmo then to GTalk.

Thursday, July 30, 2009

[TODO] A JavaScript Twitter client

I'm going to create a application that like the Gravity does on Symbian S60. This is to improve my HTML/CSS/JavaScript.
  • This application is mainly written in JavaScript,
  • Will be embedded to the Twitter proxy project birdnest, for some reason.
  • Build UI/function for the personal timeline, as no login is needed.
Update on 17 Aug: First draft released on byethost. But only support IE and Safari now. Update on 14 Sep: Deploy it on the AppEngine, it's now support Firefox either.

Thursday, July 23, 2009

Get something

This(4eZepuWr) would help me to get something that I want to have for a long time. I really want to post the English version here. But my English is poor. So I wait till now. Update: Finally, I can't get it.

Friday, June 5, 2009

Twitter

These days, I focused on the Twitter. I got many news/information from it. But thanks to the firewall, I know even more on the proxy.