Monday, June 27, 2011

Get Images Bookmarklet

I wonder why all Internet browsers do not provide us with a built-in and simple way to download multiple images, such as those excellent photos from my favorite Boston.com's The Big Picture. The closest thing that fit my need is Bulk Image Downloader and Firefox Extensions (Image Picker). The thing is, I certainly don't want to pay for something that can be free, and secondly, I don't use Firefox as my primary Internet browser (Hail Opera!)

My first plan was to make an Opera extension similar to Firefox's Image Picker, which basically read a page, select the images and then call the built-in download manager to save it to local folder. However, I'm having a real hard time finding the Opera API function to call the Opera download manager to download even a single url. So, I end up writing just this simple bookmarklet to grab the images url, and execute Free Download Manager to perform the download. For now, the bookmarklet only extract direct source url of images on the page, not linked images (such as google image search, flickr, etc.)

UPDATE: It now extracts the real image url of Google Image Search and Yahoo Image Search results :)

UPDATE 2: For Opera User, the bookmarklet will extract the url in links, so you can use the Link Panel, Select All, and Save to Download Folder. No longer need to copy paste to Free Download Manager.

You can add this link to your bookmark folder or drag it to your Opera Bookmark Bar
Get Images Bookmarklet

UPDATE 3: Added Check / Uncheck All Buttons Get Images Bookmarklet v3

UPDATE 4: Add Bing image search support Get Images Bookmarklet v4

Google Chrome or Firefox version of the bookmarklet: Get Images

Here is how you use it:

1. Go to your favorite image gallery site. Here are some of my favorites:



2. Click the Get Images Bookmarklet from your bookmark folder or Bookmark Bar, it will open a new page with all the images from the site resized along with a checkbox next to each images

3. Check or uncheck the images you want to download, and the image source url will be copied to the textarea.

4. Select all (Ctrl + A) and Copy (Ctrl + C) the links in the textbox

5. Open Free Download Manager, choose Import list of URLs from clipboard (Ctrl + Shift + V)

Comments are greatly appreciated :)

Wednesday, June 08, 2011

FBNotify.py

#coding=utf-8
#FBNotify.py: Facebook Simple Notifier
#  by Herry Limantoro (mataherry@gmail.com)
#
#NOTE: Don't forget to Add the Mechanize source folder into your SL4A scripts folder (/mnt/sdcard/sl4a/scripts)
#      http://wwwsearch.sourceforge.net/mechanize/download.html


import android
import time
import sys
import traceback
import urllib
import mechanize
import BeautifulSoup
import re

droid = android.Android()

#Setup Browser
br = mechanize.Browser()
br.set_handle_redirect(True)
br.set_handle_robots(False)

#User Agent, can't do without it
br.addheaders = [('User-agent','Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]

url = 'http://m.facebook.com/notifications.php'

#Set username password here, leave blank to prompt for username/password
username = ''
password = ''

#Set run interval (in minutes), prompt if 0
interval = 0

def get_interval():
  droid.dialogCreateAlert('Run interval (in minutes)')
  droid.dialogSetItems(['5', '15','30','60'])
  droid.dialogShow()
  response = droid.dialogGetResponse().result['item']
  if response == 0:
    interval = 5
  elif response == 1:
    interval = 15
  elif response == 2:
    interval = 30
  elif response == 3:
    interval = 60
  print "Run every " + str(interval) + " minutes"
  return interval

def run_loop():
  val = True
  errcount = 0

  #keep CPU run, still can't find other workaround
  droid.wakeLockAcquirePartial()

  while val:
    runTime = time.strftime('%Y%m%d %H%M', time.localtime())
    print 'Run at: ' + runTime
    try:
      val = get_notifications()
    except Exception, err:
      print err
      droid.notify('FBNotify Error at ' + runTime, str(err) + '\nCheck SL4A Console for detail')
      traceback.print_exc()
      errcount = errcount + 1

    #last 3 run produce exception
    if errcount > 3:
      val = False
    
    if val:
      time.sleep(interval * 60)

  droid.wakeLockRelease()

def get_notifications():
  print 'Connecting to Facebook...'
  br.open(url)

  if br.viewing_html() is False:
    print 'Viewing HTML Error'
  elif 'Notifications' in br.title(): 
    #Already logged in
    print 'Notification page'
    process()
  else:
    #Redirected to Login Form
    print 'Login ' + username

    #Select Form, Fill in username password, and Submit
    br.select_form(nr=0)
    br.form['email'] = username
    br.form['pass'] = password
    resp = br.submit()

    if br.viewing_html() is False:
      print 'Viewing HTML Error!'
    elif 'Notifications' in br.title():
      print 'Logged In! Notification page'
      process()
    else:
      #if not logged in, most likely wrong username password
      print 'Login Error!'
      #Play some tone
      droid.mediaPlay('/sdcard/media/facebook_ringtone_pop.m4a')
      droid.vibrate(500)
      droid.notify('FB Login Error - Program Exit','Check your username password')
      #logical thing to do is exit program
      return False

  return True

def process():
  soup = BeautifulSoup.BeautifulSoup(br.response().read())

  #Get all classes containing 'acw apm' (Check your FB notifications.php source if different)
  nodes = soup.findAll('div',{'class':re.compile(r'.*\bacw apm')})
  msg = ''
  count = 0
  for node in nodes:
    line = ''
    for content in node.contents:
      try:
        line = line + content.string
      except:
        line = line

    #New notification indicator
    dot = u'•'
    if line != '':
      #print out all notifications
      print line.encode('utf-8')

      #collect the new ones only to notify
      if line[0] == dot:
        if count == 0:
          msg = line
        else:
          msg = msg + '\n' + line
        count = count + 1

  if count > 0:
    print 'New notifications:'
    print msg.encode('utf-8')

    #Play some tone
    droid.mediaPlay('/sdcard/media/facebook_ringtone_pop.m4a')
    droid.vibrate(500)

    #display notification
    droid.notify('You have ' + str(count) + ' FB notifications', msg)

    #uncomment to show toast message
    #droid.makeToast(msg)
  else:
    print 'No new notification'

#Main program
valid = True
try:
  if username == '':
    username = droid.dialogGetInput('Username','Your Facebook username').result

  if password == '':
    password = droid.dialogGetPassword('Password', 'For ' + username).result

  if interval == 0:
    interval = get_interval()
except:
  valid = False

if valid:
  run_loop()

Android Facebook Simple Notifier using SL4A

Like many Android phone users, I wonder why the Android Market Facebook app lacks push notifications like BB or iPhone. Currently it only notify when there is new message, or event and friend request. So, when I get acquainted with SL4A, this is the first app pop up in my mind. However, reading through the Facebook API and having to handle oAuth and stuffs seem just too much work. So, I thought if only I could open my mobile version of FB notification page (http://m.facebook.com/notifications.php) and read the new notifications, that would do it. And upon googling on emulate browser using python, I found these two excellent tutorials:
http://stockrt.github.com/p/emulating-a-browser-in-python-with-mechanize/
http://www.ibm.com/developerworks/linux/library/l-python-mechanize-beautiful-soup/

 I guess the neat trick is to "disguise" the User Agent of the mechanize Browser. From there on, it's basically parsing the HTML source behind the notification page. One last bit is detecting the bullet list character as the indicator of new notifications, which actually made me lost in encoding decoding -.-. Oh ya, I couldn't work out the wakeLockAcquirePartial and wakeLockRelease without messing up the sleep timer. So I ended up just calling wakeLockAcquirePartial to keep the CPU run all the time while the phone is locked and screen is off. But well, at least it works :D. And oh, have I said I did all the coding and debugging on my Samsung Galaxy Gio phone :P?


Here is what you need to do:

(You can click the links, or you can just scan the goo.gl barcodes)




1. Install SL4A and Python for your Android phone
http://code.google.com/p/android-scripting/


  


2. Download Mechanize for python (stable zip), extract, copy only the mechanize source folder to SL4A scripts folder on your phone (/mnt/sdcard/SL4A/scripts/)
http://wwwsearch.sourceforge.net/mechanize/download.html




 3. Download the script FBNotify.py and save it to SL4A scripts folder

For those having trouble getting it from dropbox http://mataherry.blogspot.com/2011/06/fbnotifypy.html

4. Try it out, let me know if it doesn't work, Enjoy :D and tell others





5. Drop me a comment or e-mail me or join the SL4A Discussion Group