Skip to content

Instantly share code, notes, and snippets.

@WincerChan
Last active September 26, 2023 07:19
Show Gist options
  • Save WincerChan/362331456a6e0417c5aa1cf3ff7be2b7 to your computer and use it in GitHub Desktop.
Save WincerChan/362331456a6e0417c5aa1cf3ff7be2b7 to your computer and use it in GitHub Desktop.
导出qq聊天记录的小脚本(需要{qq号}.db和IMEI码)
from hashlib import md5
from sqlite3 import connect as sql_conn
from time import localtime, strftime
class IllegalException(Exception):
def __init__(self, *args):
super().__init__(*args)
class IMEI:
@staticmethod
def check(IMEI: str):
if len(IMEI) != 15:
return False
evens = [int(x)*2 for x in IMEI[1:14:2]]
odds = [int(x) for x in IMEI[0:14:2]]
evens_sum = [int(y) for x in evens for y in list(str(x))]
tmp = (10 - sum(evens_sum+odds) % 10) % 10
return tmp == int(IMEI[-1])
def __new__(cls, IMEI_str: str) -> str:
if not IMEI.check(IMEI_str):
raise IllegalException("The IMEI is illegal.")
return IMEI_str
class DBFile:
@staticmethod
def check(file: str):
from os import path
return path.isfile(file)
def __new__(self, file):
if not DBFile.check(file):
raise FileNotFoundError("The DataBase does not found.")
return file
class QQNum:
@staticmethod
def check(num: str):
return num.isdigit()
def __new__(self, num):
if not QQNum.check(num):
raise IllegalException("QQ number must be integer.")
return num
class QQDataBase:
def __init__(self, IMEI=None, DB=None, num=None):
self.DB = sql_conn(DB)
self.IMEI = IMEI
self.qq_num = num
self.num_to_remark = {}
self.data_dict = {} # key = timestamp
def decrypt(self, foo):
return ''.join([chr(ord(x) ^ ord(self.IMEI[i % 15]))
for i, x in enumerate(foo)]) if type(foo) is str else \
b''.join([bytes([x ^ ord(self.IMEI[i % 15])])
for i, x in enumerate(foo)]) if type(foo) is bytes else \
None
def get_remark(self):
remarks = self.DB.execute("SELECT uin, remark, name FROM Friends")
for cor in remarks:
num = self.decrypt(cor[0])
remark = self.decrypt(cor[1]) or self.decrypt(cor[2])
self.num_to_remark[num] = remark
def get_msg(self):
messages = self.DB.execute(
"SELECT msgData, senderuin, time FROM mr_friend_{}_New".format(
md5(self.qq_num.encode('utf-8')).hexdigest().upper()))
for msg in messages:
try:
msg_data = self.decrypt(msg[0]).decode('utf-8')
except UnicodeDecodeError:
msg_data = "[图片]"
uid = self.decrypt(msg[1])
self.data_dict[msg[2]] = [uid, msg_data]
def export(self):
with open('{}.txt'.format(self.qq_num), 'a') as f:
for key in self.data_dict:
time = strftime("%Y-%m-%d %H:%M:%S", localtime(key))
remark = self.num_to_remark[self.data_dict[key][0]]
msg = self.data_dict[key][1]
f.write('{}:\t{}\n{}\n'.format(time, remark, msg))
print('Success! Saved in {}.txt .'.format(self.qq_num))
exit()
def serialize(self):
self.get_remark()
self.get_msg()
self.export()
if __name__ == "__main__":
File, IMEI_, qq_num = [None] * 3
while True:
try:
File = DBFile(input('Please input database name: ')
) if not File else File
IMEI_ = IMEI(input('Pleass input phone IMEI: ')
) if not IMEI_ else IMEI_
qq_num = QQNum(input('Please input a QQ number: ')
) if not qq_num else qq_num
db = QQDataBase(IMEI_, File, qq_num)
db.serialize()
except (FileNotFoundError, IllegalException) as e:
print(e, "Please try again.")
except Exception as e:
print(e)
exit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment