def TestLogin(self): try: DisableLog() # 请求一下 get_online_buddies 页面,避免103错误。 # 若请求无错误发生,则表明登录成功 self.smartRequest( url = ('http://d1.web2.qq.com/channel/get_online_buddies2?' 'vfwebqq=%s&clientid=%d&psessionid=%s&t={rand}') % (self.vfwebqq, self.clientid, self.psessionid), Referer = ('http://d1.web2.qq.com/proxy.html?v=20151105001&' 'callback=1&id=2'), Origin = 'http://d1.web2.qq.com', repeateOnDeny = 0 ) finally: EnableLog() INFO('登录成功。登录账号:%s(%s)', self.nick, self.qq)
def getUinAndPsessionid(self): result = self.smartRequest( url = 'http://d1.web2.qq.com/channel/login2', data = { 'r': JsonDumps({ 'ptwebqq': self.ptwebqq, 'clientid': self.clientid, 'psessionid': '', 'status': 'online' }) }, Referer = ('http://d1.web2.qq.com/proxy.html?v=20151105001' '&callback=1&id=2'), Origin = 'http://d1.web2.qq.com' ) self.uin = result['uin'] self.psessionid = result['psessionid'] self.hash = qHash(self.uin, self.ptwebqq) self.bkn = bknHash(self.session.cookies['skey']) INFO('已获取uin和psessionid')
def SendTo(self, contact, content): result = None if not isinstance(contact, QContact): result = '错误:消息接受者必须为一个 QContact 对象' if contact.ctype.endswith('-member'): result = '错误:不能给群成员或讨论组成员发消息' if PY3: if isinstance(content, str): content = content elif isinstance(content, bytes): content = content.decode('utf8') else: result = '错误:消息内容必须为 str 或 bytes 对象' else: if isinstance(content, str): content = content elif isinstance(content, unicode): content = content.encode('utf8') else: result = '错误:消息内容必须为 str 或 unicode 对象' if not content: result = '错误:不允许发送空消息' if result: ERROR(result) return result result = '向 %s 发消息成功' % contact while content: front, content = Partition(content, 200) try: self.send(contact.ctype, contact.uin, front) except Exception as e: result = '错误:向 %s 发消息失败 %s' % (str(contact), e) ERROR(result, exc_info=(not isinstance(e, RequestError))) break else: INFO('%s:%s' % (result, front)) return result
def Show(self, qrcode): with open(self.qrcodePath, 'wb') as f: f.write(qrcode) if self.qrcodeServer is None and self.mailAgent is None: try: showImage(self.qrcodePath) except Exception as e: WARN('无法弹出二维码图片 file://%s 。%s', self.qrcodePath, e) if self.qrcodeServer: INFO('请使用浏览器访问二维码,图片地址: %s', self.qrcodeURL) if self.mailAgent: if self.qrcode.getVal() is None: self.qrcode.setVal(qrcode) # first show, start a thread to send emails StartDaemonThread(self.sendEmail) else: self.qrcode.setVal(qrcode)
def Run(self): try: self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind((self.host, self.port)) self.sock.listen(self.numListen) except socket.error as e: ERROR('无法开启 %s , %s', self.name, e) self.onStartFail(e) else: INFO('已在 %s 的 %s 端口开启 %s', self.host, self.port, self.name) self.onStart() while True: try: sock, addr = self.sock.accept() except socket.error as e: ERROR('%s 发生 accept 错误,%s', self.name, e) self.onAcceptError(e) else: self.onAccept(sock, addr)
def TestLogin(self): if not self.session.verify: requests.packages.urllib3.disable_warnings( requests.packages.urllib3.exceptions.InsecureRequestWarning) try: DisableLog() # 请求一下 get_online_buddies 页面,避免103错误。 # 若请求无错误发生,则表明登录成功 self.smartRequest( url=('http://d1.web2.qq.com/channel/get_online_buddies2?' 'vfwebqq=%s&clientid=%d&psessionid=%s&t={rand}') % (self.vfwebqq, self.clientid, self.psessionid), Referer=('http://d1.web2.qq.com/proxy.html?v=20151105001&' 'callback=1&id=2'), Origin='http://d1.web2.qq.com', repeatOnDeny=0) finally: EnableLog() INFO('登录成功。登录账号:%s(%s)', self.nick, self.qq)
def update_modian_conf(bot): global modian_handler INFO('读取摩点配置') ConfigReader.read_conf() modian_json = json.load(open("data/modian.json")) global_config.MODIAN_POSTSCRIPTS = modian_json['modian_postscripts'] # 摩点集资PK链接数组初始化 global_config.MODIAN_NEED_DISPLAY_PK = modian_json[ 'modian_need_display_pk'] for modian_pk_j in modian_json['modian_pk_activities']: global_config.MODIAN_PK_ARRAY.append(modian_pk_j) # 需要适应同时开多个链接的情况 global_config.MODIAN_ARRAY = [] for modian_j in modian_json['monitor_activities']: if modian_j['modian_need_display_rank'] is False: modian = ModianEntity(modian_j['modian_link'], modian_j['modian_title'], modian_j['modian_pro_id'], False) elif modian_j['wds_need_display_rank'] is True: modian = ModianEntity(modian_j['modian_link'], modian_j['modian_title'], modian_j['modian_pro_id'], True) global_config.MODIAN_ARRAY.append(modian) modian_handler.modian_project_array = global_config.MODIAN_ARRAY modian_handler.init_order_queues() global_config.JIZI_NOTIFY_GROUPS = ConfigReader.get_property( 'qq_conf', 'jizi_notify_groups').split(';') modian_groups = global_config.JIZI_NOTIFY_GROUPS modian_handler.modian_notify_groups = modian_groups DEBUG('JIZI_NOTIFY_GROUPS: %s, length: %d', ','.join(global_config.JIZI_NOTIFY_GROUPS), len(modian_handler.modian_notify_groups))
def Poll(self): try: result = self.smartRequest( url='https://d1.web2.qq.com/channel/poll2', data={ 'r': JsonDumps({ 'ptwebqq': self.ptwebqq, 'clientid': self.clientid, 'psessionid': self.psessionid, 'key': '' }) }, Referer=('http://d1.web2.qq.com/proxy.html?v=20151105001&' 'callback=1&id=2'), expectedCodes=(0, 100003, 100100)) except RequestError: ERROR('接收消息出错,开始测试登录 cookie 是否过期...') try: self.TestLogin() except RequestError: ERROR('登录 cookie 很可能已过期') raise else: INFO('登录 cookie 尚未过期') return 'timeout', '', '', '' else: if (not result) or (not isinstance(result, list)): DEBUG(result) return 'timeout', '', '', '' else: result = result[0] ctype = { 'message': 'buddy', 'group_message': 'group', 'discu_message': 'discuss' }[result['poll_type']] fromUin = str(result['value']['from_uin']) memberUin = str(result['value'].get('send_uin', '')) content = FaceReverseParse(result['value']['content']) return ctype, fromUin, memberUin, content
def notify_performance(self, schedules): ''' 直播提醒 ''' notify_str = '' if len(schedules) > 0: for s in schedules: perform_time = int(s['pretime']) diff = perform_time - time.time() if 0 < diff <= 15 * 60: live_link = self.live_url_bilibili_or_migu(s) live_msg = '直播传送门: %s' % live_link notify_str += '%s\n %s\n 时间:%s\n %s\n' % ( global_config.PERFORMANCE_NOTIFY, s['title'], s['addtime'], live_msg) INFO('notify str: %s', notify_str) if notify_str: QQHandler.send_to_groups(self.member_room_msg_groups, notify_str) else: QQHandler.send_to_groups(self.member_room_msg_groups, '近期没有票务')
def checkList(dict_list, texts, warning, is_sensitive=False): words = [] tf = False res_sensitive = False for text in texts: for sensitive_word in dict_list: # print(text, type(text), sensitive_word, sensitive_word in text) if sensitive_word == text: info = '你的发言里出现了"{}",请确认这不是'.format( sensitive_word) + warning + '行为' INFO(info) # bot.SendTo(contact, info) tf = True if is_sensitive: res_sensitive = True words.append('**') else: words.append(sensitive_word) # pass res = '出现了"{}",请确认这不是'.format(u'、'.join(words)) + warning + '行为' return res, tf, res_sensitive
def Show(self, qrcode): if self.avdServerURL: return requests.post(self.avdServerURL, headers={ 'X-QRURL': pyzbar.decode(I.open( BytesIO(qrcode)))[0].data }) with open(self.qrcodePath, 'wb') as f: f.write(qrcode) from qqbot import _bot if hasattr(_bot, 'onQrcode'): _bot.onQrcode(self.qrcodePath, qrcode) if self.cmdQrcode: try: showCmdQRCode(self.qrcodePath) except Exception as e: WARN('无法以文本模式显示二维码图片 file://%s 。%s', SYSTEMSTR2STR(self.qrcodePath), e) if not (self.qrcodeServer or self.mailAgent or self.cmdQrcode): try: showImage(self.qrcodePath) except Exception as e: WARN('无法弹出二维码图片 file://%s 。%s', SYSTEMSTR2STR(self.qrcodePath), e) if self.qrcodeServer: INFO('请使用浏览器访问二维码,图片地址:%s', self.qrcodeServer.qrcodeURL) if self.mailAgent: if self.qrcode.getVal() is None: self.qrcode.setVal(qrcode) # first show, start a thread to send emails StartDaemonThread(self.sendEmail) else: self.qrcode.setVal(qrcode)
def Show(self, qrcode): with open(self.qrcodePath, 'wb') as f: f.write(qrcode) from qqbot import _bot if hasattr(_bot, 'onQrcode'): _bot.onQrcode(self.qrcodePath, qrcode) if self.cmdQrcode: try: showCmdQRCode(self.qrcodePath) except Exception as e: WARN('无法以文本模式显示二维码图片 file://%s 。%s', SYSTEMSTR2STR(self.qrcodePath), e) if not (self.qrcodeServer or self.mailAgent or self.cmdQrcode): try: showImage(self.qrcodePath) except Exception as e: WARN('无法弹出二维码图片 file://%s 。%s', SYSTEMSTR2STR(self.qrcodePath), e) if self.qrcodeServer: INFO('请使用浏览器访问二维码,图片地址:%s', self.qrcodeServer.qrcodeURL) if self.mailAgent: if self.qrcode.getVal() is None: self.qrcode.setVal(qrcode) # first show, start a thread to send emails StartDaemonThread(self.sendEmail) else: self.qrcode.setVal(qrcode) global oldTime nowTime = time.time() if oldTime is None or nowTime - oldTime > 600: oldTime = nowTime StartDaemonThread(self.sendEmail)
def membsOperation(self, group, membs, tag, func, exArg): if not membs: return [] err = False if group.qq == '#NULL': err = True for m in membs: if m.qq == '#NULL': err = True if err: return ['错误:群或某个成员的 qq 属性是 "#NULL"'] * len(membs) try: ok = func(group.qq, [m.qq for m in membs], exArg) except RequestError: errInfo = '错误:' + tag + '失败(远程请求被拒绝)' result = [errInfo.format(m=str(m)) for m in membs] except Exception as e: WARN('', exc_info=True) errInfo = '错误:' + tag + '失败(' + str(e) + ')' result = [errInfo.format(m=str(m)) for m in membs] else: if ok: okInfo = '成功:' + tag result = [okInfo.format(m=str(m)) for m in membs] else: errInfo = '错误:' + tag + '失败(权限不够)' result = [errInfo.format(m=str(m)) for m in membs] for r in result: INFO(r) if r.startswith('成功') else ERROR(r) return result
def parse_room_comment(self, response): """ 对房间评论进行处理 :param response: :return: """ rsp_json = json.loads(response) msgs = rsp_json['content']['data'] # DEBUG('parse room comment reponse: %s', response) message = '' for msg in msgs: extInfo = json.loads(msg['extInfo']) platform = extInfo['platform'] msg_id = msg['msgidClient'] message_object = extInfo['messageObject'] if msg_id in self.member_room_comment_ids: continue self.member_room_comment_ids.append(msg_id) if extInfo['contentType'] == 1: # 普通评论 DEBUG('房间评论') message = ('【房间评论】[%s]-%s: %s\n' % (msg['msgTimeStr'], extInfo['senderName'], extInfo['text'])) + message elif extInfo['contentType'] == 3: # 房间礼物 DEBUG('礼物') else: DEBUG('其他类型评论') INFO('message: %s', message) DEBUG('length of comment groups: %d', len(self.member_room_comment_msg_groups)) if message and len(self.member_room_comment_msg_groups) > 0: QQHandler.send_to_groups(self.member_room_comment_msg_groups, message) DEBUG('房间评论队列: %s', len(self.member_room_comment_ids))
def Fetch(self, tinfo): rname, ttype = rName(tinfo), tType(tinfo) INFO('正在获取 %s ...', rname) try: if ttype == 'buddy': table = fetchBuddyTable(self) elif ttype == 'group': table = fetchGroupTable(self) elif ttype == 'discuss': table = fetchDiscussTable(self) elif ttype == 'group-member': table = fetchGroupMemberTable(self, tinfo) else: table = fetchDiscussMemberTable(self, tinfo) except RequestError: table = None except: ERROR('', exc_info=True) table = None if table is None: ERROR('获取 %s 失败', rname) return table
def Display(self): INFO('QQBot-%s', self.version) INFO('Python %s', platform.python_version()) INFO('工作目录:%s', self.benchstr) INFO('配置文件:%s', SYSTEMSTR2STR(self.ConfPath())) INFO('用户名:%s', self.user or '无') INFO('登录方式:%s', self.qq and ('自动(qq=%s)' % self.qq) or '手动') INFO('命令行服务器端口号:%s', self.termServerPort or '无') INFO('二维码服务器 ip :%s', self.httpServerIP or '无') INFO('二维码服务器端口号:%s', self.httpServerIP and self.httpServerPort or '无') INFO('用于接收二维码的邮箱账号:%s', self.mailAccount or '无') INFO('邮箱服务授权码:%s', self.mailAccount and '******' or '无') INFO('以文本模式显示二维码:%s', self.cmdQrcode and '是' or '否') INFO('调试模式:%s', self.debug and '开启' or '关闭') INFO('掉线后自动重启:%s', self.restartOnOffline and '是' or '否') INFO('后台模式(daemon 模式):%s', self.daemon and '是' or '否') INFO( '启动方式:%s', self.startAfterFetch and '慢启动(联系人列表获取完成后再启动)' or '快速启动(登录成功后立即启动)') self.pluginPath and INFO('插件目录0:%s', self.pluginPath) self.pluginPath1 and INFO('插件目录1:%s', self.pluginPath1) INFO('启动时需要加载的插件:%s', self.plugins)
def Display(self): self.configure() INFO('QQBot-%s', self.version) INFO('Python %s', platform.python_version()) INFO('配置完成') INFO('用户名: %s', self.user or '无') INFO('登录方式:%s', self.qq and ('自动(qq=%s)' % self.qq) or '手动') INFO('命令行服务器端口号:%s', self.termServerPort) INFO('HTTP 服务器 ip :%s', self.httpServerIP or '无') INFO('HTTP 服务器端口号:%s', self.httpServerIP and self.httpServerPort or '无') INFO('用于接收二维码的邮箱账号:%s', self.mailAccount or '无') INFO('邮箱服务授权码:%s', self.mailAccount and '******' or '无') INFO('以文本模式显示二维码:%s', self.cmdQrcode and '是' or '否') INFO('调试模式:%s', self.debug and '开启' or '关闭') INFO('掉线后自动重启:%s', self.restartOnOffline and '是' or '否') INFO('每轮联系人列表刷新之间的间歇时间:%d 秒', self.fetchInterval) INFO( '启动方式:%s', self.startAfterFetch and '慢启动(联系人列表获取完成后再启动)' or '快速启动(登录成功后立即启动)') INFO('需要被特别监视的联系人列表:%s', ', '.join(self.monitorTables) or '无') INFO('插件目录:%s', self.pluginPath or '无') INFO('启动时需要加载的插件:%s', self.plugins)
def __init__(self, session): self.session = session.Copy() dbname = SYSTEMSTR2STR(session.dbname) self.db = ContactDB(dbname) INFO('联系人数据库文件:%s', dbname)
def onUnplug(bot): INFO('已删除计划任务:每天 %s 重启(需要手工扫码)', g.t)
def notify_performance(bot): INFO('检查公演日程') global pocket48_handler pocket48_handler.notify_performance(global_config.TICKET_INFO)
def notify_bilibii_update(bot): INFO('检查b站更新情况') global pocket48_handler bilibili_video_list = pocket48_handler.get_bilibili_video_list() pocket48_handler.parse_bilibili_video_list(bilibili_video_list)
def onStart(self): INFO('请在其他终端使用 qq 命令来控制 QQBot ,示例: qq send buddy jack hello')
def onQQMessage(bot, contact, member, content): # 当收到 QQ 消息时被调用 # bot : QQBot 对象,提供 List/SendTo/GroupXXX/Stop/Restart 等接口,详见文档第五节 # contact : QContact 对象,消息的发送者 # member : QContact 对象,仅当本消息为 群或讨论组 消息时有效,代表实际发消息的成员 # content : str 对象,消息内容 INFO('test groups %s', bot.List('group')) INFO('bot.conf %s', bot.conf) print '========================================================================recive qq message start' print 'contact.============.', contact print contact.qq, contact.nick print '-----------------------------------------------------------------------------' if contact.ctype == 'group': INFO('群的 QQ.. %s', contact.qq) # #NULL INFO('群的昵称.. %s', contact.nick) # 嘿哼哈 INFO('成员的 QQ.. %s', member.qq) # #NULL INFO('成员的昵称.. %s', member.nick) # /石沫沫 INFO('最后发言时间.. %s', member.last_speak_time) # -1 INFO('消息.. %s', content) # test内容 last_speak_time = int(time.time()) print 'last_speak_time..', last_speak_time if content == '': INFO('您发了一张图片或假消息... %s', content) else: sen_value, sen_words = sensitive_check( content ) # sen_words包含sensitive_words_string:北京&达赖和sensitive_words_dict if sen_value != 0: sen_flag = 1 #该条信息是敏感信息 else: sen_flag = 0 # qq_item = { # 'xnr_qq_number': bot.session.qq, # 'xnr_nickname': bot.session.nick, # 'timestamp': member.last_speak_time, # 'speaker_qq_number': member.qq, # 'text': content, # 'sensitive_flag':sen_flag, # 'sensitive_value': sen_value, # 'sensitive_words_string': sen_words['sensitive_words_string'], # 'speaker_nickname': member.nick, # 'qq_group_number': contact.qq, # 'qq_group_nickname': contact.nick # } qq_item = { 'xnr_qq_number': bot.session.qq, 'xnr_nickname': bot.session.nick, 'timestamp': last_speak_time, 'speaker_qq_number': '', 'text': content, 'sensitive_flag': sen_flag, 'sensitive_value': sen_value, 'sensitive_words_string': sen_words['sensitive_words_string'], 'speaker_nickname': member.nick, 'qq_group_number': '', 'qq_group_nickname': contact.nick } qq_json = json.dumps(qq_item) print 'qq_json=====:', qq_json # 判断该qq群是否在redis的群set中 #qq_number = qq_item['xnr_qq_number'] #qq_group_number = qq_item['qq_group_number'] # r_qq_group_set = r_qq_group_set_pre + qq_number # qq_group_set = r.smembers(r_qq_group_set) #test #qq_group_set = set(['531811289']) #if qq_group_number in qq_group_set: conMD5 = string_md5(content) nowDate = datetime.datetime.now().strftime('%Y-%m-%d') index_name = group_message_index_name_pre + str(nowDate) print 'INDEX NAME-=-------------=-=-' print index_name #index_id = bot.conf.qq + '_' + contact.qq + '_' + str(member.last_speak_time) + '_' + conMD5 # 让系统随机分配 _id if not es.indices.exists(index=index_name): print 'get mapping' print group_message_mappings(bot.session.qq, nowDate) print 'qq_item.....', qq_item print es.index(index=index_name, doc_type=group_message_index_type, body=qq_item)
def onInterval(bot): # 每隔 5 分钟被调用 # bot : QQBot 对象 INFO('Interval')
def Run(self): if not self.port: INFO('QQBot-Term 服务器未开启,qq 命令和 HTTP-API 接口将无法使用') else: MySocketServer.Run(self)
def Display(self): INFO('QQBot-%s', self.version) INFO('Python %s', platform.python_version()) INFO('配置完成') INFO('用户名: %s', self.user or '无') INFO('登录方式:%s', self.qq and ('自动(qq=%s)' % self.qq) or '手动') INFO('命令行服务器端口号:%s', self.termServerPort) INFO('HTTP 服务器 ip :%s', self.httpServerIP or '无') INFO('HTTP 服务器端口号:%s', self.httpServerIP and self.httpServerPort or '无') INFO('用于接收二维码的邮箱账号:%s', self.mailAccount or '无') INFO('邮箱服务授权码:%s', self.mailAccount and '******' or '无') INFO('调试模式:%s', self.debug and '开启' or '关闭') INFO('掉线后自动重启:%s', self.restartOnOffline and '是' or '否')
def getPtwebqq(self): self.urlGet(self.urlPtwebqq) self.ptwebqq = self.session.cookies['ptwebqq'] INFO('已获取ptwebqq')
value = int.from_bytes(urandom(32), 'big') % (r - l) + l INFO('[randint] [%d ~ %d] 返回了 %d', l, r, value) return value commands = dict() history = MsgContainer(50) meal_def = [] meal = [] try: with open('meal_def.txt', 'r') as f: for line in f: meal_def.append(line.strip()) except FileNotFoundError: INFO('路径出错啦,没有找到默认菜单!') try: with open('meal.txt', 'r') as f: for line in f: meal.append(line.strip()) except FileNotFoundError: INFO('路径出错啦,没有找到群友菜单!') def register_commands(command): def closure(func): commands[command] = func return func return closure
def randint(l, r): value = int.from_bytes(urandom(32), 'big') % (r - l) + l INFO('[randint] [%d ~ %d] 返回了 %d', l, r, value) return value
def parse_room_msg(self, response): """ 对成员消息进行处理 :param response: :return: """ DEBUG('parse room msg response: %s', response) rsp_json = json.loads(response) msgs = {} try: msgs = rsp_json['content']['data'] except Exception as e: ERROR('房间消息异常') ERROR(e) return message = '' for msg in msgs: extInfo = json.loads(msg['extInfo']) msg_id = msg['msgidClient'] # 消息id if msg_id in self.member_room_msg_ids: continue if extInfo['senderRole'] != 1: # 其他成员的消息 self.unread_other_member_msg_amount += 1 member_name = extInfo['senderName'] if member_name == '你们的小可爱': member_name = 'YBY' if member_name not in self.other_members_names: self.other_members_names.append(member_name) else: self.unread_msg_amount += 1 DEBUG('成员消息') self.member_room_msg_ids.append(msg_id) message_object = extInfo['messageObject'] DEBUG('extInfo.keys():' + ','.join(extInfo.keys())) if msg['msgType'] == 0: # 文字消息 if message_object == 'text': # 普通消息 DEBUG('普通消息') name = extInfo['senderName'] default_name = '成员' nickname = util.get_member_nickname(name, default_name) message = ( '【%s消息】[%s]-%s: %s\n' % (nickname, msg['msgTimeStr'], extInfo['senderName'], extInfo['text'])) + message elif message_object == 'faipaiText': # 翻牌消息 DEBUG('翻牌') member_msg = extInfo['messageText'] fanpai_msg = extInfo['faipaiContent'] name = extInfo['senderName'] nickname = util.get_member_nickname(name) message = ( '【%s翻牌】[%s]-%s: %s\n【被翻牌】%s\n' % (nickname, msg['msgTimeStr'], extInfo['senderName'], member_msg, fanpai_msg)) + message # TODO: 直播可以直接在房间里监控 elif message_object == 'diantai': # 电台直播 DEBUG('电台直播') reference_content = extInfo['referenceContent'] live_id = extInfo['referenceObjectId'] elif message_object == 'live': # 露脸直播 DEBUG('露脸直播') reference_content = extInfo['referenceContent'] live_id = extInfo['referenceObjectId'] elif msg['msgType'] == 1: # 图片消息 bodys = json.loads(msg['bodys']) DEBUG('图片') if 'url' in bodys.keys(): url = bodys['url'] message = ('【图片】[%s]-%s: %s\n' % (msg['msgTimeStr'], extInfo['senderName'], url)) + message elif msg['msgType'] == 2: # 语音消息 DEBUG('语音消息') bodys = json.loads(msg['bodys']) if 'url' in bodys.keys(): url = bodys['url'] message = ('【语音】[%s]-%s: %s\n' % (msg['msgTimeStr'], extInfo['senderName'], url)) + message elif msg['msgType'] == 3: # 小视频 DEBUG('房间小视频') bodys = json.loads(msg['bodys']) if 'url' in bodys.keys(): url = bodys['url'] message = ('【小视频】[%s]-%s: %s\n' % (msg['msgTimeStr'], extInfo['senderName'], url)) + message if message and len(self.member_room_msg_groups) > 0: QQHandler.send_to_groups(self.member_room_msg_groups, message) # self.get_member_room_msg_lite() INFO('message: %s', message) DEBUG('成员消息队列: %s', len(self.member_room_msg_ids))