#coding:utf8
import urllib
import urllib2
import cookielib
import json
import hashlib
import os
import poster
import random
import time
import subprocess

token = ''

def login(email, password):
    cookie = cookielib.LWPCookieJar('cookie.txt')
    opener = poster.streaminghttp.register_openers()
    opener.add_handler(urllib2.HTTPCookieProcessor(cookie))

    req = urllib2.Request('https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN', urllib.urlencode({'username': email, 'pwd':hashlib.md5(password).hexdigest(), 'imgcode':'', 'f':'json'}))
    req.add_header('Referer', 'https://mp.weixin.qq.com')
    rep = urllib2.urlopen(req).read()
    cookie.save()
    
    result = json.loads(rep)

    if 'base_resp' in result and result['base_resp']['ret'] == 0:
        
        #buy ticket
        def assistant():
            get = { 
                    '1':'1'
            }
            post = {
                    'action':'get_ticket',
                    'auth':'ticket'
            }
            rep = transfer('https://mp.weixin.qq.com/misc/safeassistant', get, post, None)
            return rep['ticket']
        ticket = assistant()
        if ticket == None:
            return None
        
        # change the card
        def qrconnect(t):
            url = 'https://mp.weixin.qq.com/safe/safeqrconnect'
            get = { 
                    '1':'1'
            }
            post = {
                    'appid':'wx3a432d2dbe2442ce',
                    'scope':'snsapi_contact',
                    'state':'0',
                    'redirect_uri':'https://mp.weixin.qq.com',
                    'login_type':'safe_center',
                    'type':'json',
                    'ticket':ticket,
            }
            def uuid(url, rep):
                rep = json.loads(rep)
                if rep.has_key('uuid'):
                    return rep
                return None

            rep = transfer(url , get, post, None, uuid)
            if rep == None:
                return None
            return rep['uuid']
        uuid = qrconnect(ticket)
        if uuid == None:
            return None
        #sequential number
        #i don't know how to make it, but it must be made in client.
        msgid = '407438052'
        
        #print the card
        def qrcode(ticket, uuid):
            url = 'https://mp.weixin.qq.com/safe/safeqrcode'
            get = {
                    'ticket':ticket,
                    'uuid':uuid,
                    'action':'check',
                    'type':'login',
                    'auth':'ticket',
                    'msgid':msgid,
            }
            def qrcode(url, rep):
                img = 'qr.jpg'
                with open(img, 'wb') as qr:
                    qr.write(rep)
                return img
            return transfer(url, get, None, None, qrcode)
        img = qrcode(ticket, uuid)

        #checking the card
        def safeuuid(uuid):
            url = 'https://mp.weixin.qq.com/safe/safeuuid'
            get = {
                    'timespam':str(time.time()).replace('.', ''),
                    'token':'',
                    }
            post = {
                    'token':'',
                    'uuid':uuid,
                    'action':'json',
                    'type':'json',
                    }                    
            def pass_ack(url, resp):
                resp = json.loads(resp)
                if resp.has_key('code'):
                    return resp['code']
                return None

            return transfer(url , get, post, None, pass_ack)
        if sys.platform == 'win32':
            subprocess.Popen('mspaint %s' % img)
        elif sys.platform == 'darwin':
            subprocess.Popen(['open', img])
        else:
            print 'could not open the qr image.'
            sys.exit(0)
        code = None
        while code == None:
            code = safeuuid(uuid)

        os.remove(img)

        #verify the account
        def verify(email, msgid, code):
            url = 'https://mp.weixin.qq.com/cgi-bin/securewxverify'
            post = {
                'token':'',
                'code':code,
                'account':email,
                'operation_seq':msgid
            }

            def verify_ack(url, r):
                return r
            return transfer(url , None, post, None)
        result = verify(email, msgid, code)
        return result['redirect_url'].split("=")[-1]

def logout():
    urllib2.urlopen('https://mp.weixin.qq.com/cgi-bin/logout?t=wxm-logoout')

def transfer(url, get = None, post = None, header = None, ack = None):
    time.sleep(1)
    query = {'lang':'zh_CN', 'token':token} 
    if get != None:
        get.update(query)
        get.update({'f':'json'})
        url = url + '?' + urllib.urlencode(get)
    if post != None:
        if type(post) == dict:
            post.update(query)
            post.update({'ajax':1, 'random':random.random()})
            if 't' not in post.keys():
                post['t'] = 'ajax-response'
            post = urllib.urlencode(post)
        req = urllib2.Request(url, post)
    else:
        req = urllib2.Request(url)

    req.add_header('Referer', 'https://mp.weixin.qq.com')

    if header != None:
        for k,v in header.items():
            req.add_header(k, v)
    rep = urllib2.urlopen(req).read()
    if ack == None:
        def ack(url, rep):
            rep = json.loads(rep)
            if rep['base_resp']['ret'] != 0:
                print url, '->', rep
                return None
            return rep
    return ack(url, rep)

def ticket():
    rep = transfer('https://mp.weixin.qq.com/cgi-bin/message', get={'t':'message/list', 'count':20, 'day':0})
    if rep == None:
        return None, None
    user = rep['user_info']['user_name']
    media = rep['base_resp']['media_ticket']
    return user, media

def upload_image(path):
    user, media = ticket()
    if user == None:
        return None
    url = 'https://mp.weixin.qq.com/cgi-bin/filetransfer'
    get = {
        'action':'upload_material',
        'f':'json',
        'writetype':'doublewrite',
        'groupid':1,
        'ticket_id':user,
        'ticket':media,
        'token':token,
    }
    field = {'file': open(path, 'rb'), 'filename':'test.jpg'}
    post, header = poster.encode.multipart_encode(field)
    rep = transfer(url, get, post, header)
    return rep['content']


def add_message(cover, title, content, digest='', author='', source=''):
    url = 'https://mp.weixin.qq.com/cgi-bin/operate_appmsg'
    post = {
            'AppMsgId': '', 
            'count': 1, 
            'sub': 'create',
            'type': 10,
            'title0':title,
            'content0':content,
            'digest0':digest,
            'author0':author,
            'fileid0':cover,
            'sourceurl0':source,
            'show_cover_pic0':0,
            'shortvideofileid0':'',
            'copyright_type0':0,
            'releasefirst0':0,
            'can_reward0':0,
            'reward_wording0':'',
            'reprint_permit_type0':0,
            'original_article_type0':'',
            'need_open_comment0':1,

            }
    rep = transfer(url, post=post)
    return rep['appMsgId']
def send_mass_message(msg_id, gender=0, group_id=-1):
    url = 'https://mp.weixin.qq.com/cgi-bin/masssendpage'
    get = {
            't':'mass/send',
    }
    rep = transfer(url, get)
    op = rep['operation_seq']
    #administractor's certification 
def image_path():
    url = 'https://mp.weixin.qq.com/cgi-bin/filepage'
    get = {
            'type':2, 
            't':'media/img_list',
    }
    rep = transfer(url, get)
    id_path = {}
    for image in rep['page_info']['file_item']:
            id_path[image['file_id']] = image['cdn_url'].replace('\/', '/')
    return id_path


if __name__ ==  '__main__':
    import sys
    import re
    import markdown2
    import anydbm
    token = login(sys.argv[1], sys.argv[2])
    if token == None:
        print 'failure to login'
        sys.exit(0)
    imgs = anydbm.open('cache.db', 'c')
    root = sys.argv[3]
    if sys.argv[3].find('cook') == -1:
        source = 'http://note.codepongo.com/article/' + sys.argv[4][:-len('.md')]
    else:
        source = 'http://cook.codepongo.com/' + sys.argv[4][:-len('.md')]

    with open(os.path.join(root, sys.argv[4])) as f:
        title = f.readline()[:-1]
        f.readline()
        content = f.read()
    cover = None
    for img in re.findall(re.compile(r"\!\[.*\]\((.*)\)"), content):
        # if the image is already in server, path is the image id
        # the code does not process this situation :(
        # i will fix it later.
        imgs[img] = upload_image(os.path.join(root, img))
        if cover == None:
            cover = imgs[img]

    server = image_path()
    # improve compatibility
    if sys.platform == 'darwin':
        for k in imgs.keys():
            local_path = k
            local_id = imgs[k]
            for server_id, server_path in server.items():
                if server_id == int(local_id):
                    imgs[local_path] = server_path
        for k in imgs.keys():
            v = imgs[k]
            content = content.replace(k, v)
    else:
        for local_path, local_id in imgs.items():
            for server_id, server_path in server.items():
                if server_id == int(local_id):
                    imgs[local_path] = server_path
    
        for k, v in imgs.items():
            content = content.replace(k, v)
    content = markdown2.markdown(content).replace('<h2>', '<br /><br /><h2><b>').replace('</h2>', '</b></h2><br /><br />').encode('utf8')
    add_message(cover, title, content, author='Zuo Haitao(codepongo)', source=source)
    logout()
    if sys.platform == 'darwin':
        os.remove('cache.db.db')
    else:
        os.remove('cache.db')