Last active
September 26, 2023 07:19
-
-
Save WincerChan/362331456a6e0417c5aa1cf3ff7be2b7 to your computer and use it in GitHub Desktop.
导出qq聊天记录的小脚本(需要{qq号}.db和IMEI码)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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