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
===
[]()
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)
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
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[]()\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.