reorx
6/15/2011 - 5:47 AM

xiami auto checkin script

xiami auto checkin script

#!/usr/bin/python2.7
#coding=utf-8

import sys
import time
import gzip
import logging
import urllib, httplib
from Cookie import BaseCookie
from StringIO import StringIO

## configs ##

USER = {
    'email':'',
    'password':'',
}

BASIC_HEADERS = {
    'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'
}

CHECKIN_EXTRA_HEADERS = {
    'Host':'www.xiami.com',
    'User-Agent':'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.10 (maverick) Firefox/3.6.17',
    'Accept':'*/*',
    'Accept-Language':'zh-cn,zh;q=0.5',
    #'Accept-Encoding':'gzip,deflate',
    # if set 'gzip', gzip will be received..
    'Accept-Charset':'GB2312,utf-8;q=0.7,*;q=0.7',
    #'Keep-Alive':'115',
    'Connection':'keep-alive',
    'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
    'X-Requested-With':'XMLHttpRequest',
    'Referer':'http://www.xiami.com/',
    'Content-Length':'0'
}

class MXLogger(object):
    Path = 'xiami.log.txt'
    DLine = '--------------------%s----------------------\n' % \
            time.strftime('%Y-%m-%d', time.localtime())
    WGap = '    '

    def __init__(self):
        logger = logging.getLogger()

        hdr = logging.FileHandler(self.Path)
        logFormat = self.WGap.join([time.strftime('%H:%M:%S'), '%(levelname)s', '%(message)s'])
        formatter = logging.Formatter(logFormat)
        hdr.setFormatter(formatter)
        logger.addHandler(hdr)
        logger.setLevel(logging.NOTSET)
        self.l = logger

        # add daily divide line
        with open(self.Path, 'a') as f:
            f.write(self.DLine)

    def __call__(self, a, l=0):
        if isinstance(a, Exception):
            msg = 'ERROR: %s, %s' % (a.__class__.__name__, a.message)
            self.l.error(msg)
        else:
            msg = self.WGap*l + a
            self.l.info(msg)

class Xiami(object):
    DOMAIN = 'www.xiami.com'

    def __init__(self, user):
        self.user = user
        self.logger = MXLogger()

    # function wrapper NOTE no better than @decorator ?
    def __getattribute__(self, key):
        attr = super(Xiami, self).__getattribute__(key)
        if callable(attr) and key != 'logger': #and not key.startswith('_'):
            self.logger('Going: %s' % key)
        return attr

    def _conn(self):
        return httplib.HTTPConnection(self.DOMAIN)

    def _fetch(self, url, data, method='POST', extra_headers=None):
        conn = self._conn()

        headers = BASIC_HEADERS
        if extra_headers:
            headers.update(extra_headers)

        self.logger('req: '+url, 1)

        conn.request(method, url, data, headers)
        resp = conn.getresponse()

        # decompress if response has been gziped
        raw_body = resp.read()
        if 'gzip' == resp.getheader('Content-Encoding'):
            self.logger('* decompressing gzip data', 1)
            buff = StringIO(raw_body)
            gzipf = gzip.GzipFile(fileobj=buff)
            resp.body = gzipf.read()
        else:
            resp.body = raw_body

        self.logger('resp: %s    %s' % (resp.status, resp.body), 1)

        return resp

    def login(self):
        form = {
            'autologin':1,
            'done':'/',
            'type':'',
            'email': self.user['email'],
            'password': self.user['password'],
            'submit':'登录'
        }
        data = urllib.urlencode(form)

        resp = self._fetch('/member/login', data)

        try:
            _cookie = resp.getheader('Set-Cookie')
        except:
            _cookie = resp.getheader('set-cookie')
        if not _cookie:
            raise ValueError('cookie value is None')
        cookie = BaseCookie(_cookie)
        self.auth_token = cookie['member_auth'].value

    def checkin(self):
        # token's existence reprsent the success of authentication/login
        if not hasattr(self, 'auth_token'):
            self.login()

        extra_headers = {
            'Cookie': 'member_auth='+self.auth_token
        }
        extra_headers.update(CHECKIN_EXTRA_HEADERS)
        self._fetch('/task/signin', None, extra_headers=extra_headers)

    def run(self):
        try:
            self.checkin()
        except Exception as e:
            self.logger(e)
        finally:
            sys.exit()
        
if '__main__' == __name__:
    xm = Xiami(USER)
    xm.run()