Full Code of gera2ld/qqlib for AI

master 1c6417ea4d60 cached
14 files
49.5 KB
23.0k tokens
41 symbols
1 requests
Download .txt
Repository: gera2ld/qqlib
Branch: master
Commit: 1c6417ea4d60
Files: 14
Total size: 49.5 KB

Directory structure:
gitextract_m9887sgl/

├── .editorconfig
├── .gitignore
├── README.md
├── qqlib/
│   ├── __init__.py
│   ├── __main__.py
│   ├── hieroglyphy/
│   │   ├── __init__.py
│   │   └── data.py
│   ├── qzone.py
│   └── tea.py
├── requirements.txt
├── setup.py
└── tests/
    ├── __init__.py
    ├── test_hieroglyphy.py
    └── test_tea.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[*.py]
indent_size = 4


================================================
FILE: .gitignore
================================================
__pycache__/
*.pyc
python*/
*.egg-info/
/build
/dist


================================================
FILE: README.md
================================================
qqlib
===
[![PyPI](https://img.shields.io/pypi/v/qqlib.svg)]()

Python版QQ登录库,兼容Python2.x和Python3.x。

安装
---
``` sh
$ pip install qqlib
# or
$ pip install git+https://github.com/gera2ld/qqlib.git
```

快速开始
---
``` sh
$ python -m qqlib
```

高级用法
---
``` python
def login(qq):
    # 不考虑验证码的情况,直接登录
    qq.login()

import qqlib
qq = qqlib.QQ(12345678, 'password')
login(qq)
print('Hi, %s' % qq.nick)
```

登录时有可能出现需要验证码的情况,可以捕获到`qqlib.NeedVerifyCode`错误。这时`qq.need_verify`为`True`,需要获取验证码图片(`qq.verifier.fetch_image()`)进行处理,验证(`qq.verifier.verify(code)`)之后再继续登录。下面是支持输入验证码的`login`方法:
``` python
def login(qq):
    # 自动重试登录
    while True:
        try:
            if qq.need_verify:
                open('verify.jpg', 'wb').write(qq.verifier.fetch_image())
                print('验证码已保存到verify.jpg')
                # 输入验证码
                vcode = input('请输入验证码:')
                qq.verifier.verify(vcode)
            qq.login()
            break
        except qqlib.NeedVerifyCode as exc:
            if exc.message:
                print('Error:', exc.message)
```

QZone:
``` python
from qqlib import qzone
qq = qzone.QZone(12345678, 'password')
# 登录流程同上
login(qq)
qq.feed('发一条说说')
```

测试
---
``` sh
# Python 2
$ python -m unittest discover

# Python 3
$ python3 -m unittest
```


================================================
FILE: qqlib/__init__.py
================================================
'''
QQ Login module
Licensed to MIT
'''

import hashlib, re, binascii, base64
import rsa, requests
from . import tea

__all__ = ['QQ', 'LogInError', 'NeedVerifyCode']

class LogInError(Exception): pass

class NeedVerifyCode(Exception):
    def __init__(self, verifier, message=None):
        Exception.__init__(self)
        self.verifier = verifier
        self.message = message

class Verifier:
    url_check = 'http://check.ptlogin2.qq.com/check'
    url_gettype = 'http://captcha.qq.com/cap_union_new_gettype'
    url_getsig = 'http://captcha.qq.com/cap_union_new_getsig'
    url_getimage = 'http://captcha.qq.com/cap_union_new_getcapbysig'
    url_verify = 'http://captcha.qq.com/cap_union_new_verify'

    def __init__(self, parent):
        self.parent = parent
        self.sess = None
        self.need_verify = False

    def check(self):
        parent = self.parent
        login_sig = parent.session.cookies['pt_login_sig']
        g = parent.fetch(self.url_check, params={
            'pt_tea': 2,
            'uin': parent.user,
            'appid': parent.appid,
            'js_ver': parent.js_ver,
            'js_type': 1,
            'u1': parent.url_success,
            'login_sig': login_sig,
        }).text
        v = re.findall('\'(.*?)\'', g)
        self.pt_vcode_v1, self.cap_cd, self.uin, self.ptvfsession = v[:4]
        if self.pt_vcode_v1 == '1':
            self.throw()
        else:
            self.vcode = self.cap_cd

    def get_type(self):
        parent = self.parent
        g = parent.fetch(self.url_gettype, params={
            'aid': parent.appid,
            'protocol': 'http',
            'clienttype': 2,
            'apptype': 2,
            'curenv': 'inner',
            'uid': parent.user,
            'cap_cd': self.cap_cd,
            'callback': '_qqlib_',
        }).text
        m = re.search('"sess":"(.*?)"', g)
        self.sess = m.group(1)

    def fetch_image(self):
        parent = self.parent
        if self.sess is None:
            self.get_type()
        g = parent.fetch(self.url_getsig, params={
            'aid': parent.appid,
            'protocol': 'http',
            'clienttype': 2,
            'apptype': 2,
            'curenv': 'inner',
            'sess': self.sess,
            'uid': parent.user,
            'cap_cd': self.cap_cd,
        }).json()
        self.vsig = g['vsig']
        r = parent.fetch(self.url_getimage, params={
            'aid': parent.appid,
            'protocol': 'http',
            'clienttype': 2,
            'apptype': 2,
            'curenv': 'inner',
            'sess': self.sess,
            'uid': parent.user,
            'cap_cd': self.cap_cd,
            'vsig': self.vsig,
            'showtype': 'embed',
            'ischartype': 1,
        })
        return r.content

    def verify(self, vcode):
        parent = self.parent
        r = parent.fetch(self.url_verify, data={
            'aid': parent.appid,
            'protocol': 'http',
            'clientype': 2,
            'apptype': 2,
            'curenv': 'inner',
            'sess': self.sess,
            'uid': parent.user,
            'cap_cd': self.cap_cd,
            'vsig': self.vsig,
            'ans': vcode,
        })
        r.encoding='utf-8'
        g = r.json()
        if g['errorCode'] != '0':
            self.throw(g['errMessage'])
        self.vcode = g['randstr']
        self.ptvfsession = g['ticket']
        self.need_verify = False

    def throw(self, message=None):
        self.need_verify = True
        raise NeedVerifyCode(self, message)

class QQ:
    appid = 549000912
    action = '4-22-1450611437613'
    url_success = 'http://qzs.qq.com/qzone/v5/loginsucc.html?para=izone'
    js_ver = 10171

    def __init__(self, user, pwd):
        self.user = user
        self.pwd = pwd
        self.nick = None
        self.verifier = None
        self.session = requests.Session()
        self.xlogin()

    def fetch(self, url, data=None, **kw):
        if data is None:
            func = self.session.get
        else:
            kw['data'] = data
            func = self.session.post
        return func(url, **kw)

    url_xlogin = 'http://xui.ptlogin2.qq.com/cgi-bin/xlogin'
    def xlogin(self):
        '''
        Get a log-in signature in cookies.
        '''
        self.fetch(self.url_xlogin, params={
            'proxy_url': 'http://qzs.qq.com/qzone/v6/portal/proxy.html',
            'daid': 5,
            'no_verifyimg': 1,
            'appid': self.appid,
            's_url': self.url_success,
        })

    url_login = 'http://ptlogin2.qq.com/login'
    def login(self, force=False):
        login_sig = self.session.cookies['pt_login_sig']
        if force:
            self.verifier = None
        if self.verifier is None:
            verifier = self.verifier = Verifier(self)
            verifier.check()
        else:
            verifier = self.verifier
        ptvfsession = verifier.ptvfsession or self.session.cookies.get('ptvfsession', '')
        g = self.fetch(self.url_login, params={
            'u': self.user,
            'verifycode': verifier.vcode,
            'pt_vcode_v1': verifier.pt_vcode_v1,
            'pt_verifysession_v1': ptvfsession,
            'p': self.pwdencode(verifier.vcode, verifier.uin, self.pwd),
            'pt_randsalt': 0,
            'u1': self.url_success,
            'ptredirect': 0,
            'h': 1,
            't': 1,
            'g': 1,
            'from_ui': 1,
            'ptlang': 2052,
            'action': self.action,
            'js_ver': self.js_ver,
            'js_type': 1,
            'aid': self.appid,
            'daid': 5,
            'login_sig': login_sig,
        }).text
        r = re.findall('\'(.*?)\'', g)
        if r[0] == '4':
            verifier.throw(r[4])
        if r[0] != '0':
            raise LogInError(r[4])
        self.nick = r[5]
        self.fetch(r[2])
        self.verifier = None

    @property
    def need_verify(self):
        return self.verifier and self.verifier.need_verify

    def fromhex(self, s):
        # Python 3: bytes.fromhex
        return bytes(bytearray.fromhex(s))

    pubKey = rsa.PublicKey(int(
        'F20CE00BAE5361F8FA3AE9CEFA495362'
        'FF7DA1BA628F64A347F0A8C012BF0B25'
        '4A30CD92ABFFE7A6EE0DC424CB6166F8'
        '819EFA5BCCB20EDFB4AD02E412CCF579'
        'B1CA711D55B8B0B3AEB60153D5E0693A'
        '2A86F3167D7847A0CB8B00004716A909'
        '5D9BADC977CBB804DBDCBA6029A97108'
        '69A453F27DFDDF83C016D928B3CBF4C7',
        16
    ), 3)
    def pwdencode(self, vcode, uin, pwd):
        '''
        Encode password with tea.
        '''
        # uin is the bytes of QQ number stored in unsigned long (8 bytes)
        salt = uin.replace(r'\x', '')
        h1 = hashlib.md5(pwd.encode()).digest()
        s2 = hashlib.md5(h1 + self.fromhex(salt)).hexdigest().upper()
        rsaH1 = binascii.b2a_hex(rsa.encrypt(h1, self.pubKey)).decode()
        rsaH1Len = hex(len(rsaH1) // 2)[2:]
        hexVcode = binascii.b2a_hex(vcode.upper().encode()).decode()
        vcodeLen = hex(len(hexVcode) // 2)[2:]
        l = len(vcodeLen)
        if l < 4:
            vcodeLen = '0' * (4 - l) + vcodeLen
        l = len(rsaH1Len)
        if l < 4:
            rsaH1Len = '0' * (4 - l) + rsaH1Len
        pwd1 = rsaH1Len + rsaH1 + salt + vcodeLen + hexVcode
        saltPwd = base64.b64encode(
            tea.encrypt(self.fromhex(pwd1), self.fromhex(s2))
        ).decode().replace('/', '-').replace('+', '*').replace('=', '_')
        return saltPwd


================================================
FILE: qqlib/__main__.py
================================================
import getpass, sys, tempfile, os
from . import QQ, NeedVerifyCode

quser = input('QQ: ')
qpwd = getpass.getpass('Password: ')

qq = QQ(quser, qpwd)
while True:
    try:
        if qq.need_verify:
            fd, path = tempfile.mkstemp(suffix='.jpg')
            os.write(fd, qq.verifier.fetch_image())
            os.close(fd)
            print('Verify code is saved to:', path)
            vcode = input('Input verify code: ')
            os.remove(path)
            qq.verifier.verify(vcode)
        qq.login()
        break
    except NeedVerifyCode:
        exc = sys.exc_info()[1]
        if exc.message:
            print('Error:', exc.message)
        exc = None
print('Hi, %s' % qq.nick)


================================================
FILE: qqlib/hieroglyphy/__init__.py
================================================
'''
Decode hieroglyphy with Python
@author Gerald <i@gerald.top>

Reference:
- http://patriciopalladino.com/files/hieroglyphy/
- https://github.com/alcuadrado/hieroglyphy

QZone uses hieroglyphy but changed `f`
'''

# Generate mappings with JavaScript:
# Run it at http://patriciopalladino.com/files/hieroglyphy/
# > 'mappings = ' + JSON.stringify('0123456789abcdeghijklmnopqrstuvwxyz'.split('').reduce((res, c) => {res[c] = hieroglyphy.hieroglyphyString(c).replace(/\+\[\]$/, ''); return res;}, {f:'(![]+[])[+[]]'}), null, 4)
# Store it to ./data.py
from .data import mappings

class CannotDecodeError(Exception): pass

def decode(text):
    remained = text
    results = []
    while remained:
        for key, val in mappings.items():
            if remained == val or remained.startswith(val + '+'):
                results.append(key)
                remained = remained[len(val) + 1:]
                break
        else:
            print(''.join(results), remained)
            raise CannotDecodeError(text)
    return ''.join(results)


================================================
FILE: qqlib/hieroglyphy/data.py
================================================
mappings = {"0":"(+[]+[])","1":"(+!![]+[])","2":"(!+[]+!![]+[])","3":"(!+[]+!![]+!![]+[])","4":"(!+[]+!![]+!![]+!![]+[])","5":"(!+[]+!![]+!![]+!![]+!![]+[])","6":"(!+[]+!![]+!![]+!![]+!![]+!![]+[])","7":"(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])","8":"(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])","9":"(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])","f":"(![]+[])[+[]]","a":"(+{}+[])[+!![]]","b":"([]+{})[!+[]+!![]]","c":"([]+{})[!+[]+!![]+!![]+!![]+!![]]","d":"([][[]]+[])[!+[]+!![]]","e":"([][[]]+[])[!+[]+!![]+!![]]","g":"[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[]))","h":"([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[+[]]","i":"([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]","j":"([]+{})[!+[]+!![]+!![]]","k":"[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+[])+([]+{})[!+[]+!![]])","l":"(![]+[])[!+[]+!![]]","m":"[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+[])+([][[]]+[])[!+[]+!![]])","n":"([][[]]+[])[+!![]]","o":"([]+{})[+!![]]","p":"([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]","q":"[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(+!![]+[]))","r":"(!![]+[])[+!![]]","s":"(![]+[])[!+[]+!![]+!![]]","t":"(!![]+[])[+[]]","u":"([][[]]+[])[+[]]","v":"[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+[]))","w":"[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[]))","x":"[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[]))","y":"(+(+!![]+([][[]]+[])[!+[]+!![]+!![]]+(+!![]+[])+(+[]+[])+(+[]+[])+(+[]+[]))+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]","z":"[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(+{}+[])[+!![]])"}


================================================
FILE: qqlib/qzone.py
================================================
'''
QZone module
'''

from . import QQ
from . import hieroglyphy

class QZone(QQ):
    url_success = 'http://qzs.qq.com/qzone/v5/loginsucc.html?para=izone'
    url_feed = 'http://taotao.qzone.qq.com/cgi-bin/emotion_cgi_publish_v6'
    url_home = 'https://user.qzone.qq.com/'

    def g_tk(self):
        h = 5381
        cookies = self.session.cookies
        s = cookies.get('p_skey') or cookies.get('skey') or ''
        for c in s:
            h += (h << 5) + ord(c)
        return h & 0x7fffffff

    def _qzonetoken(self, res, start_str, end_str=';'):
        i = res.find(start_str)
        j = res.find(';', i)
        assert i > 0, 'qzonetoken not found!'
        raw = res[i + len(start_str) : j]
        return hieroglyphy.decode(raw)

    def qzonetoken(self):
        self.fetch(self.url_success)
        res = self.fetch(self.url_home + str(self.user), headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36',
        }).text
        return self._qzonetoken(res, 'window.g_qzonetoken = (function(){ try{return ')

    def _feed(self, data):
        return self.fetch(self.url_feed, params={
            'g_tk': self.g_tk(),
            'qzonetoken': self.qzonetoken(),
        }, data = {
            'syn_tweet_verson'    : 1,
            'paramstr'            : 1,
            'pic_template'        : '',
            'richtype'            : '',
            'richval'             : '',
            'special_url'         : '',
            'subrichtype'         : '',
            'who'                 : 1,
            'con'                 : data,
            'feedversion'         : 1,
            'ver'                 : 1,
            'ugc_right'           : 1,
            'to_tweet'            : 0,
            'to_sign'             : 0,
            'hostuin'             : self.user,
            'code_version'        : 1,
            'format'              : 'fs'
        })

    def feed(self, data):
        res = self._feed(data)
        res.raise_for_status()

class MQZone(QZone):
    url_success = 'https://h5.qzone.qq.com/mqzone/index'
    url_feed = 'https://mobile.qzone.qq.com/mood/publish_mood'

    def qzonetoken(self):
        res = self.fetch(self.url_success).text
        return self._qzonetoken(res, 'window.shine0callback = (function(){ try{return ')

    def _feed(self, data):
        return self.fetch(self.url_feed, params={
            'g_tk': self.g_tk(),
            'qzonetoken': self.qzonetoken(),
        }, data = {
            'opr_type': 'publish_shuoshuo',
            'res_uin': self.user,
            'content': data,
            'richval': '',
            'lat': 0,
            'lon': 0,
            'lbsid': '',
            'issyncweibo': 0,
            'format': 'json',
        })


================================================
FILE: qqlib/tea.py
================================================
'''
QQ Crypt module
Licensed to MIT
'''

import struct, ctypes
import os

__all__ = ['encrypt', 'decrypt']

def xor8B(a, b):
    '''
    XOR operation between two 8B bytes.
    '''
    length = 8
    arr_a = bytearray(a[:length])
    arr_b = bytearray(b[:length])
    for i in range(length):
        arr_a[i] ^= arr_b[i]
    return bytes(arr_a) if isinstance(a, bytes) else arr_a

def encipher(v, k):
    '''
    TEA coder encrypt 64 bits value, by 128 bits key,
    QQ uses 16 round TEA.
    http://www.ftp.cl.cam.ac.uk/ftp/papers/djw-rmn/djw-rmn-tea.html .
    '''
    n=16  #qq use 16
    delta = 0x9e3779b9
    k = struct.unpack('!LLLL', k[0:16])
    y, z = map(ctypes.c_uint32, struct.unpack('!LL', v[0:8]))
    s = ctypes.c_uint32(0)
    for i in range(n):
        s.value += delta
        y.value += (z.value << 4) + k[0] ^ z.value+ s.value ^ (z.value >> 5) + k[1]
        z.value += (y.value << 4) + k[2] ^ y.value+ s.value ^ (y.value >> 5) + k[3]
    r = struct.pack('!LL', y.value, z.value)
    return r

def encrypt(v, k):
    """
    Encrypt function for QQ.

    v is the message to encrypt, k is the key
    fill char is randomized (which is 0xAD in old version)
    the length of the final data is filln + 8 + len(v)

    The message is encrypted 8 bytes at at time,
    the result is:

    r = encipher( v ^ tr, key) ^ to   (*)

    `encipher` is the QQ's TEA function.
    v is 8 bytes data to be encrypted.
    tr is the result in preceding round.
    to is the data coded in perceding round (v_pre ^ r_pre_pre)
    For the first 8 bytes 'tr' and 'to' is filled by zero.
    """
    vl = len(v)
    #filln = (8 - (vl + 2)) % 8
    filln = (6 - vl) % 8
    v_arr = (
        bytes(bytearray([filln | 0xf8])),
        os.urandom(filln + 2),  # random char * (filln + 2)
        v,
        b'\0' * 7,
    )
    v = b''.join(v_arr)
    tr = to = b'\0' * 8
    r = []
    for i in range(0, len(v), 8):
        o = xor8B(v[i:i+8], tr)
        tr = xor8B(encipher(o, k), to)
        to = o
        r.append(tr)
    r = b''.join(r)
    return r

def decrypt(v, k):
    """
    Decrypt function for QQ.

    according to (*) we can get:

    x  = decipher(v[i:i+8] ^ prePlain, key) ^ preCyrpt

    prePlain is the previously encrypted 8 bytes:
       per 8 byte from v XOR previous preCyrpt
    preCrypt is previous 8 bytes of encrypted data.

    After decrypting, we must truncate the padding bytes.
    The number of padding bytes in the front of message is
    pos + 1.
    pos is the first byte of deCrypted: r[0] & 0x07 + 2
    The number of padding bytes in the end is 7 (b'\0' * 7).
    The returned value is r[pos+1:-7].

    >>> from binascii import a2b_hex, b2a_hex
    >>> r = encrypt('', b2a_hex('b537a06cf3bcb33206237d7149c27bc3'))
    >>> decrypt(r, b2a_hex('b537a06cf3bcb33206237d7149c27bc3'))
    ''
    >>> r = encrypt('abcdefghijklimabcdefghijklmn', b2a_hex('b537a06cf3bcb33206237d7149c27bc3'))
    >>> decrypt(r, b2a_hex('b537a06cf3bcb33206237d7149c27bc3'))
    'abcdefghijklimabcdefghijklmn'
    >>> import md5
    >>> key = md5.new(md5.new('python').digest()).digest()
    >>> data='8CE160B9F312AEC9AC8D8AEAB41A319EDF51FB4BB5E33820C77C48DFC53E2A48CD1C24B29490329D2285897A32E7B32E9830DC2D0695802EB1D9890A0223D0E36C35B24732CE12D06403975B0BC1280EA32B3EE98EAB858C40670C9E1A376AE6C7DCFADD4D45C1081571D2AF3D0F41B73BDC915C3AE542AF2C8B1364614861FC7272E33D90FA012620C18ABF76BE0B9EC0D24017C0C073C469B4376C7C08AA30'
    >>> data = a2b_hex(data)
    >>> b2a_hex(decrypt(data, key))
    '00553361637347436654695a354d7a51531c69f1f5dde81c4332097f0000011f4042c89732030aa4d290f9f941891ae3670bb9c21053397d05f35425c7bf80000000001f40da558a481f40000100004dc573dd2af3b28b6a13e8fa72ea138cd13aa145b0e62554fe8df4b11662a794000000000000000000000000dde81c4342c8966642c4df9142c3a4a9000a000a'

    """
    l = len(v)
    #if l % 8 != 0 or l < 16:
    #    return ''
    prePlain = decipher(v, k)
    pos = ord(prePlain[:1]) & 0x07 + 2
    r = prePlain
    preCrypt = v[0:8]
    for i in range(8, l, 8):
        x = xor8B(decipher(xor8B(v[i:i+8], prePlain), k), preCrypt)
        prePlain = xor8B(x, preCrypt)
        preCrypt = v[i:i+8]
        r += x
    if r[-7:] == b'\0' * 7:
        return r[pos+1:-7]

def decipher(v, k):
    '''
    TEA decipher, decrypt 64bits value with 128 bits key.
    it's the inverse function of TEA encrypt.
    '''
    n = 16
    y, z = map(ctypes.c_uint32, struct.unpack('!LL', v[0:8]))
    a, b, c, d = map(ctypes.c_uint32, struct.unpack('!LLLL', k[0:16]))
    delta = 0x9E3779B9
    s = ctypes.c_uint32(delta << 4)
    for i in range(n):
        z.value -= ((y.value << 4) + c.value) ^ (y.value + s.value) ^ ((y.value >> 5) + d.value)
        y.value -= ((z.value << 4) + a.value) ^ (z.value + s.value) ^ ((z.value >> 5) + b.value)
        s.value -= delta
    return struct.pack('!LL', y.value, z.value)


================================================
FILE: requirements.txt
================================================
rsa
requests


================================================
FILE: setup.py
================================================
from setuptools import setup, find_packages

setup(
    name='qqlib',
    version='1.1.1',
    description='QQ library for Python.',
    long_description='QQ library for Python, based on web APIs.',
    url='https://github.com/gera2ld/qqlib',
    author='Gerald',
    author_email='i@gerald.top',
    license='MIT',
    classifiers = [
        'Development Status :: 5 - Production/Stable',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.0',
        'Programming Language :: Python :: 3.1',
        'Programming Language :: Python :: 3.2',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
    ],
    keywords='qq',
    packages=find_packages(exclude=['tests']),
    install_requires=[
        'rsa',
        'requests',
    ],
)


================================================
FILE: tests/__init__.py
================================================


================================================
FILE: tests/test_hieroglyphy.py
================================================
import unittest
from qqlib import hieroglyphy

class TestHieroglyphy(unittest.TestCase):
    def test_decode(self):
        for encrypted, plain in [
            (
                '(+[]+[])+(+!![]+[])+(!+[]+!![]+[])+(!+[]+!![]+!![]+[])'
                '+(!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+[]'
                ')+(!+[]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!'
                '![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+'
                '!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]'
                '+!![]+[])+(+{}+[])[+!![]]+([]+{})[!+[]+!![]]+([]+{})[!'
                '+[]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]]+([][[]'
                ']+[])[!+[]+!![]+!![]]+(![]+[])[+[]]',
                '0123456789abcdef'
            ),
            (
                '(!+[]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!!['
                ']+!![]+[])+(+[]+[])+([][[]]+[])[!+[]+!![]]+(!+[]+!![]+'
                '!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+[])+'
                '([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[+[]]+(![]+[])[+[]'
                ']+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+([]+{})'
                '[!+[]+!![]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(['
                ']+{})[!+[]+!![]]+(+{}+[])[+!![]]+([]+{})[!+[]+!![]]+(['
                ']+{})[!+[]+!![]+!![]+!![]+!![]]+(+!![]+[])+([][[]]+[])'
                '[!+[]+!![]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+['
                '])+(!+[]+!![]+!![]+!![]+!![]+[])+([]+{})[!+[]+!![]]+(['
                '][[]]+[])[!+[]+!![]]+(!+[]+!![]+!![]+!![]+!![]+!![]+[]'
                ')+(!+[]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+[])+(!+[]+!'
                '![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+'
                '!![]+!![]+!![]+[])+([]+{})[!+[]+!![]+!![]+!![]+!![]]+('
                '!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]'
                '+[])+(![]+[])[+[]]+(![]+[])[+[]]+(+{}+[])[+!![]]+(!+[]'
                '+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!!['
                ']+!![]+!![]+!![]+!![]+!![]+!![]+[])+([]+[][(![]+[])[!+'
                '[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[]'
                ')[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!!['
                ']]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+['
                '])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]'
                '+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!'
                '![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]'
                '+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]'
                ']+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+'
                '!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})['
                '!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+['
                ']]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]'
                ']+([][[]]+[])[+!![]])())[+[]]+(!+[]+!![]+!![]+!![]+!!['
                ']+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!!'
                '[]+[])+(!+[]+!![]+!![]+[])+(+!![]+[])+(!+[]+!![]+!![]+'
                '!![]+[])+(+{}+[])[+!![]]+([][[]]+[])[!+[]+!![]]+(!+[]+'
                '!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(+{}+[])[+'
                '!![]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!!'
                '[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+['
                '])+([][[]]+[])[!+[]+!![]+!![]]+(+[]+[])+(!+[]+!![]+!!['
                ']+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!!'
                '[]+!![]+[])+(!+[]+!![]+[])+(!+[]+!![]+!![]+!![]+[])+(!'
                '+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(![]+[])[+[]]+(!'
                '+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+'
                '!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]'
                '+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+[])+([]+{})[!'
                '+[]+!![]]+(!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!!['
                ']+!![]+!![]+!![]+!![]+!![]+[])+(![]+[])[+[]]+(!+[]+!!['
                ']+!![]+!![]+!![]+[])+(!+[]+!![]+[])+([]+{})[!+[]+!![]]'
                '+(+[]+[])+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!+[]+!![]'
                '+!![]+!![]+!![]+[])+(!+[]+!![]+[])+(![]+[])[+[]]+(!+[]'
                '+!![]+!![]+!![]+[])+(![]+[])[+[]]+([]+{})[!+[]+!![]+!!'
                '[]+!![]+!![]]+([]+{})[!+[]+!![]]+(!+[]+!![]+!![]+!![]+'
                '[])+([]+{})[!+[]+!![]]+(!+[]+!![]+!![]+!![]+!![]+!![]+'
                '!![]+!![]+!![]+[])+(+{}+[])[+!![]]+(!+[]+!![]+[])+(+!!'
                '[]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!'
                '![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+'
                '!![]+!![]+!![]+!![]+!![]+!![]+[])+([]+{})[!+[]+!![]]+('
                '[]+{})[!+[]+!![]+!![]+!![]+!![]]+(!+[]+!![]+!![]+[])+('
                '[]+{})[!+[]+!![]]+(!+[]+!![]+!![]+!![]+!![]+[])+(!+[]+'
                '!![]+[])+(!+[]+!![]+[])+([]+{})[!+[]+!![]+!![]+!![]+!!'
                '[]]+(+[]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+[])+(+{}+['
                '])[+!![]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(![]'
                '+[])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])'
                '+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!+[]+!![]+!![]+!!['
                ']+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+[])+(!+[]+!!'
                '[]+!![]+[])+(+[]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!!'
                '[]+!![]+!![]+[])+(+{}+[])[+!![]]+(![]+[])[+[]]+(!+[]+!'
                '![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+'
                '!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+[])+([]+{})[!+'
                '[]+!![]]+(!+[]+!![]+!![]+[])+(+[]+[])+(+[]+[])+(!+[]+!'
                '![]+!![]+!![]+!![]+!![]+[])+([]+{})[!+[]+!![]]+(!+[]+!'
                '![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+'
                '[])+(!+[]+!![]+!![]+[])+(+{}+[])[+!![]]+(+!![]+[])+(!+'
                '[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(![]+[]'
                ')[+[]]+(!+[]+!![]+!![]+!![]+!![]+[])+([]+{})[!+[]+!![]'
                '+!![]+!![]+!![]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!'
                '![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+'
                '[])+(![]+[])[+[]]+([][[]]+[])[!+[]+!![]]+(!+[]+!![]+!!'
                '[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!'
                '![]+[])+(+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]'
                '+!![]+[])+(+[]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+[])+'
                '(![]+[])[+[]]+([]+{})[!+[]+!![]]+(!+[]+!![]+!![]+!![]+'
                '!![]+!![]+[])+([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{}'
                ')[!+[]+!![]+!![]+!![]+!![]]+(!+[]+!![]+!![]+!![]+!![]+'
                '[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]'
                '+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])',
                '290d56eff8b7babc1d85bd63477c46ffa89h96314ad9a783e06824'
                '7f9666b49f52b0c52f4fcb4b9a21798bc3b522c06a7f8c83309af9'
                '36b3006b833a19f5c98fd941806fb6cc588'
            ),
        ]:
            self.assertEqual(hieroglyphy.decode(encrypted), plain)


================================================
FILE: tests/test_tea.py
================================================
import unittest
from binascii import a2b_hex, b2a_hex
from qqlib import tea

KEY_1 = b'aaaabbbbccccdddd'
DATA_1 = b'abcdefgh'
ENC_1 = b'a557272c538d3e96'
KEY_2 = b2a_hex(b'b537a06cf3bcb33206237d7149c27bc3')
DATA_2 = b''
ENC_2 = b'b56137502728e2c74bb84c6d50d21973'

class TestTEA(unittest.TestCase):
    def test_encipher(self):
        c = b2a_hex(tea.encipher(DATA_1, KEY_1))
        self.assertEqual(c, ENC_1)

    def test_decipher(self):
        c = tea.decipher(a2b_hex(ENC_1), KEY_1)
        self.assertEqual(c, DATA_1)

    def test_decrypt(self):
        c = tea.decrypt(a2b_hex(ENC_2), KEY_2)
        self.assertEqual(c, DATA_2)

    def test_encrypt(self):
        e = tea.encrypt(DATA_2, KEY_2)
        src = tea.decrypt(e, KEY_2)
        self.assertEqual(src, DATA_2)
Download .txt
gitextract_m9887sgl/

├── .editorconfig
├── .gitignore
├── README.md
├── qqlib/
│   ├── __init__.py
│   ├── __main__.py
│   ├── hieroglyphy/
│   │   ├── __init__.py
│   │   └── data.py
│   ├── qzone.py
│   └── tea.py
├── requirements.txt
├── setup.py
└── tests/
    ├── __init__.py
    ├── test_hieroglyphy.py
    └── test_tea.py
Download .txt
SYMBOL INDEX (41 symbols across 6 files)

FILE: qqlib/__init__.py
  class LogInError (line 12) | class LogInError(Exception): pass
  class NeedVerifyCode (line 14) | class NeedVerifyCode(Exception):
    method __init__ (line 15) | def __init__(self, verifier, message=None):
  class Verifier (line 20) | class Verifier:
    method __init__ (line 27) | def __init__(self, parent):
    method check (line 32) | def check(self):
    method get_type (line 51) | def get_type(self):
    method fetch_image (line 66) | def fetch_image(self):
    method verify (line 96) | def verify(self, vcode):
    method throw (line 118) | def throw(self, message=None):
  class QQ (line 122) | class QQ:
    method __init__ (line 128) | def __init__(self, user, pwd):
    method fetch (line 136) | def fetch(self, url, data=None, **kw):
    method xlogin (line 145) | def xlogin(self):
    method login (line 158) | def login(self, force=False):
    method need_verify (line 199) | def need_verify(self):
    method fromhex (line 202) | def fromhex(self, s):
    method pwdencode (line 217) | def pwdencode(self, vcode, uin, pwd):

FILE: qqlib/hieroglyphy/__init__.py
  class CannotDecodeError (line 18) | class CannotDecodeError(Exception): pass
  function decode (line 20) | def decode(text):

FILE: qqlib/qzone.py
  class QZone (line 8) | class QZone(QQ):
    method g_tk (line 13) | def g_tk(self):
    method _qzonetoken (line 21) | def _qzonetoken(self, res, start_str, end_str=';'):
    method qzonetoken (line 28) | def qzonetoken(self):
    method _feed (line 35) | def _feed(self, data):
    method feed (line 59) | def feed(self, data):
  class MQZone (line 63) | class MQZone(QZone):
    method qzonetoken (line 67) | def qzonetoken(self):
    method _feed (line 71) | def _feed(self, data):

FILE: qqlib/tea.py
  function xor8B (line 11) | def xor8B(a, b):
  function encipher (line 22) | def encipher(v, k):
  function encrypt (line 40) | def encrypt(v, k):
  function decrypt (line 79) | def decrypt(v, k):
  function decipher (line 128) | def decipher(v, k):

FILE: tests/test_hieroglyphy.py
  class TestHieroglyphy (line 4) | class TestHieroglyphy(unittest.TestCase):
    method test_decode (line 5) | def test_decode(self):

FILE: tests/test_tea.py
  class TestTEA (line 12) | class TestTEA(unittest.TestCase):
    method test_encipher (line 13) | def test_encipher(self):
    method test_decipher (line 17) | def test_decipher(self):
    method test_decrypt (line 21) | def test_decrypt(self):
    method test_encrypt (line 25) | def test_encrypt(self):
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (53K chars).
[
  {
    "path": ".editorconfig",
    "chars": 212,
    "preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ni"
  },
  {
    "path": ".gitignore",
    "chars": 53,
    "preview": "__pycache__/\n*.pyc\npython*/\n*.egg-info/\n/build\n/dist\n"
  },
  {
    "path": "README.md",
    "chars": 1278,
    "preview": "qqlib\n===\n[![PyPI](https://img.shields.io/pypi/v/qqlib.svg)]()\n\nPython版QQ登录库,兼容Python2.x和Python3.x。\n\n安装\n---\n``` sh\n$ pip"
  },
  {
    "path": "qqlib/__init__.py",
    "chars": 7535,
    "preview": "'''\nQQ Login module\nLicensed to MIT\n'''\n\nimport hashlib, re, binascii, base64\nimport rsa, requests\nfrom . import tea\n\n__"
  },
  {
    "path": "qqlib/__main__.py",
    "chars": 698,
    "preview": "import getpass, sys, tempfile, os\nfrom . import QQ, NeedVerifyCode\n\nquser = input('QQ: ')\nqpwd = getpass.getpass('Passwo"
  },
  {
    "path": "qqlib/hieroglyphy/__init__.py",
    "chars": 1043,
    "preview": "'''\nDecode hieroglyphy with Python\n@author Gerald <i@gerald.top>\n\nReference:\n- http://patriciopalladino.com/files/hierog"
  },
  {
    "path": "qqlib/hieroglyphy/data.py",
    "chars": 23130,
    "preview": "mappings = {\"0\":\"(+[]+[])\",\"1\":\"(+!![]+[])\",\"2\":\"(!+[]+!![]+[])\",\"3\":\"(!+[]+!![]+!![]+[])\",\"4\":\"(!+[]+!![]+!![]+!![]+[])"
  },
  {
    "path": "qqlib/qzone.py",
    "chars": 2838,
    "preview": "'''\nQZone module\n'''\n\nfrom . import QQ\nfrom . import hieroglyphy\n\nclass QZone(QQ):\n    url_success = 'http://qzs.qq.com/"
  },
  {
    "path": "qqlib/tea.py",
    "chars": 4842,
    "preview": "'''\nQQ Crypt module\nLicensed to MIT\n'''\n\nimport struct, ctypes\nimport os\n\n__all__ = ['encrypt', 'decrypt']\n\ndef xor8B(a,"
  },
  {
    "path": "requirements.txt",
    "chars": 13,
    "preview": "rsa\nrequests\n"
  },
  {
    "path": "setup.py",
    "chars": 1063,
    "preview": "from setuptools import setup, find_packages\n\nsetup(\n    name='qqlib',\n    version='1.1.1',\n    description='QQ library f"
  },
  {
    "path": "tests/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/test_hieroglyphy.py",
    "chars": 7205,
    "preview": "import unittest\nfrom qqlib import hieroglyphy\n\nclass TestHieroglyphy(unittest.TestCase):\n    def test_decode(self):\n    "
  },
  {
    "path": "tests/test_tea.py",
    "chars": 780,
    "preview": "import unittest\nfrom binascii import a2b_hex, b2a_hex\nfrom qqlib import tea\n\nKEY_1 = b'aaaabbbbccccdddd'\nDATA_1 = b'abcd"
  }
]

About this extraction

This page contains the full source code of the gera2ld/qqlib GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 14 files (49.5 KB), approximately 23.0k tokens, and a symbol index with 41 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!