Spaces:
Sleeping
Sleeping
| import re, os, sys, subprocess, copy, traceback, logging | |
| try: | |
| from HTMLParser import HTMLParser | |
| except ImportError: | |
| from html.parser import HTMLParser | |
| try: | |
| from urllib import quote as _quote | |
| quote = lambda n: _quote(n.encode('utf8', 'replace')) | |
| except ImportError: | |
| from urllib.parse import quote | |
| import requests | |
| from . import config | |
| logger = logging.getLogger('itchat') | |
| emojiRegex = re.compile(r'<span class="emoji emoji(.{1,10})"></span>') | |
| htmlParser = HTMLParser() | |
| if not hasattr(htmlParser, 'unescape'): | |
| import html | |
| htmlParser.unescape = html.unescape | |
| # FIX Python 3.9 HTMLParser.unescape is removed. See https://docs.python.org/3.9/whatsnew/3.9.html | |
| try: | |
| b = u'\u2588' | |
| sys.stdout.write(b + '\r') | |
| sys.stdout.flush() | |
| except UnicodeEncodeError: | |
| BLOCK = 'MM' | |
| else: | |
| BLOCK = b | |
| friendInfoTemplate = {} | |
| for k in ('UserName', 'City', 'DisplayName', 'PYQuanPin', 'RemarkPYInitial', 'Province', | |
| 'KeyWord', 'RemarkName', 'PYInitial', 'EncryChatRoomId', 'Alias', 'Signature', | |
| 'NickName', 'RemarkPYQuanPin', 'HeadImgUrl'): | |
| friendInfoTemplate[k] = '' | |
| for k in ('UniFriend', 'Sex', 'AppAccountFlag', 'VerifyFlag', 'ChatRoomId', 'HideInputBarFlag', | |
| 'AttrStatus', 'SnsFlag', 'MemberCount', 'OwnerUin', 'ContactFlag', 'Uin', | |
| 'StarFriend', 'Statues'): | |
| friendInfoTemplate[k] = 0 | |
| friendInfoTemplate['MemberList'] = [] | |
| def clear_screen(): | |
| os.system('cls' if config.OS == 'Windows' else 'clear') | |
| def emoji_formatter(d, k): | |
| ''' _emoji_deebugger is for bugs about emoji match caused by wechat backstage | |
| like :face with tears of joy: will be replaced with :cat face with tears of joy: | |
| ''' | |
| def _emoji_debugger(d, k): | |
| s = d[k].replace('<span class="emoji emoji1f450"></span', | |
| '<span class="emoji emoji1f450"></span>') # fix missing bug | |
| def __fix_miss_match(m): | |
| return '<span class="emoji emoji%s"></span>' % ({ | |
| '1f63c': '1f601', '1f639': '1f602', '1f63a': '1f603', | |
| '1f4ab': '1f616', '1f64d': '1f614', '1f63b': '1f60d', | |
| '1f63d': '1f618', '1f64e': '1f621', '1f63f': '1f622', | |
| }.get(m.group(1), m.group(1))) | |
| return emojiRegex.sub(__fix_miss_match, s) | |
| def _emoji_formatter(m): | |
| s = m.group(1) | |
| if len(s) == 6: | |
| return ('\\U%s\\U%s'%(s[:2].rjust(8, '0'), s[2:].rjust(8, '0')) | |
| ).encode('utf8').decode('unicode-escape', 'replace') | |
| elif len(s) == 10: | |
| return ('\\U%s\\U%s'%(s[:5].rjust(8, '0'), s[5:].rjust(8, '0')) | |
| ).encode('utf8').decode('unicode-escape', 'replace') | |
| else: | |
| return ('\\U%s'%m.group(1).rjust(8, '0') | |
| ).encode('utf8').decode('unicode-escape', 'replace') | |
| d[k] = _emoji_debugger(d, k) | |
| d[k] = emojiRegex.sub(_emoji_formatter, d[k]) | |
| def msg_formatter(d, k): | |
| emoji_formatter(d, k) | |
| d[k] = d[k].replace('<br/>', '\n') | |
| d[k] = htmlParser.unescape(d[k]) | |
| def check_file(fileDir): | |
| try: | |
| with open(fileDir): | |
| pass | |
| return True | |
| except: | |
| return False | |
| def print_qr(fileDir): | |
| if config.OS == 'Darwin': | |
| subprocess.call(['open', fileDir]) | |
| elif config.OS == 'Linux': | |
| subprocess.call(['xdg-open', fileDir]) | |
| else: | |
| os.startfile(fileDir) | |
| def print_cmd_qr(qrText, white=BLOCK, black=' ', enableCmdQR=True): | |
| blockCount = int(enableCmdQR) | |
| if abs(blockCount) == 0: | |
| blockCount = 1 | |
| white *= abs(blockCount) | |
| if blockCount < 0: | |
| white, black = black, white | |
| sys.stdout.write(' '*50 + '\r') | |
| sys.stdout.flush() | |
| qr = qrText.replace('0', white).replace('1', black) | |
| sys.stdout.write(qr) | |
| sys.stdout.flush() | |
| def struct_friend_info(knownInfo): | |
| member = copy.deepcopy(friendInfoTemplate) | |
| for k, v in copy.deepcopy(knownInfo).items(): member[k] = v | |
| return member | |
| def search_dict_list(l, key, value): | |
| ''' Search a list of dict | |
| * return dict with specific value & key ''' | |
| for i in l: | |
| if i.get(key) == value: | |
| return i | |
| def print_line(msg, oneLine = False): | |
| if oneLine: | |
| sys.stdout.write(' '*40 + '\r') | |
| sys.stdout.flush() | |
| else: | |
| sys.stdout.write('\n') | |
| sys.stdout.write(msg.encode(sys.stdin.encoding or 'utf8', 'replace' | |
| ).decode(sys.stdin.encoding or 'utf8', 'replace')) | |
| sys.stdout.flush() | |
| def test_connect(retryTime=5): | |
| for i in range(retryTime): | |
| try: | |
| r = requests.get(config.BASE_URL) | |
| return True | |
| except: | |
| if i == retryTime - 1: | |
| logger.error(traceback.format_exc()) | |
| return False | |
| def contact_deep_copy(core, contact): | |
| with core.storageClass.updateLock: | |
| return copy.deepcopy(contact) | |
| def get_image_postfix(data): | |
| data = data[:20] | |
| if b'GIF' in data: | |
| return 'gif' | |
| elif b'PNG' in data: | |
| return 'png' | |
| elif b'JFIF' in data: | |
| return 'jpg' | |
| return '' | |
| def update_info_dict(oldInfoDict, newInfoDict): | |
| ''' only normal values will be updated here | |
| because newInfoDict is normal dict, so it's not necessary to consider templates | |
| ''' | |
| for k, v in newInfoDict.items(): | |
| if any((isinstance(v, t) for t in (tuple, list, dict))): | |
| pass # these values will be updated somewhere else | |
| elif oldInfoDict.get(k) is None or v not in (None, '', '0', 0): | |
| oldInfoDict[k] = v |