def onResetMACTriggered(self): resetFlag = False mac,okPressed = QInputDialog.getText(self,"MAC状态重置","请输入MAC号:",QLineEdit.Normal, " ") if okPressed and mac.strip(): print('mac:' + mac) logging.info('mac:' + mac) logging.info("\r\n") mysql = MySQLCommand(host=self.sysXMLDict['mysqlhost'],port=int(self.sysXMLDict['mysqlport']),user=self.sysXMLDict['mysqluser'],\ passwd=self.sysXMLDict['mysqlpassword'],db=self.sysXMLDict['mysqldatabase'],table=self.sysXMLDict['mysqltable']) mysqlConFlag = mysql.connectMysql() if not mysqlConFlag: self.mysqlConnectErrSignal.emit(MYSQL_CONNECT_ERROR) return self.lock.acquire() resetFlag = mysql.resetMysqlMACStatusAndSN(mac=mac,stbType=self.sysXMLDict['mysqlstbtype'],poNumber=self.poNumber) if resetFlag: QMessageBox.information(self,SUCCESSTITLE,RESET_MAC_SUCCESS) else: QMessageBox.critical(self,ERRORTITLE,RESET_MAC_FAILED) self.lock.release() mysql.closeMysql() else: QMessageBox.critical(self,ERRORTITLE,RESET_MAC_INFO)
def onBackupDBTriggered(self): self.checkMysqldumpTool() backupFlag = True fileName,okPressed = QInputDialog.getText(self,"数据库备份","请输入文件名:",QLineEdit.Normal, "dbback.sql") if okPressed and fileName.strip(): print('DBBackupFile:' + fileName) logging.info('DBBackupFile:' + fileName) logging.info("\r\n") command = 'mysqldump -u' + self.sysXMLDict['mysqluser'] + ' -h ' + self.sysXMLDict['mysqlhost'] + ' -p' + self.sysXMLDict['mysqlpassword'] \ + ' ' + self.sysXMLDict['mysqldatabase'] + ' ' + self.sysXMLDict['mysqltable'] + '>' + fileName print(command) logging.info("Backup DB command: " + command) process = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT) for line in process.stdout.readlines(): if str(line).count('error'): backupFlag = False break process.wait() if backupFlag: QMessageBox.information(self,SUCCESSTITLE,MYSQL_BACKUP_SUCCESS) else: QMessageBox.critical(self,ERRORTITLE,MYSQL_BACKUP_FAILED) else: QMessageBox.critical(self,ERRORTITLE,MYSQL_INFO_BACKUP)
def handle_danmu(self, data: dict): if 'cmd' in data: cmd = data['cmd'] elif 'msg' in data: data = data['msg'] cmd = data['cmd'] else: return True # 预防未来sbb站 if cmd == 'PREPARING': print(f'{self._area_id}号数据连接房间下播({self._room_id})') return False elif cmd == 'NOTICE_MSG': # 1 《第五人格》哔哩哔哩直播预选赛六强诞生! # 2 全区广播:<%user_name%>送给<%user_name%>1个嗨翻全城,快来抽奖吧 # 3 <%user_name%> 在 <%user_name%> 的房间开通了总督并触发了抽奖,点击前往TA的房间去抽奖吧 # 4 欢迎 <%总督 user_name%> 登船 # 5 恭喜 <%user_name%> 获得大奖 <%23333x银瓜子%>, 感谢 <%user_name%> 的赠送 # 6 <%user_name%> 在直播间 <%529%> 使用了 <%20%> 倍节奏风暴,大家快去跟风领取奖励吧!(只报20的) msg_type = data['msg_type'] real_roomid = int(data['real_roomid']) if msg_type == 2 or msg_type == 8: raffle_name = '小电视' print(f'{self._area_id}号数据连接检测到{real_roomid:^9}的{raffle_name}') self.add2rooms(real_roomid, 'TV') elif msg_type == 3: raffle_name = '舰队' print(f'{self._area_id}号数据连接检测到{real_roomid:^9}的{raffle_name}') self.add2rooms(real_roomid, 'GUARD') elif msg_type == 6: raffle_name = '二十倍节奏风暴' print(f'{self._area_id}号数据连接检测到{real_roomid:^9}的{raffle_name}') self.add2rooms(real_roomid, 'STORM') return True
async def run(self): self._waiting_end = self._loop.create_future() while not self._closed: print(f'正在启动{self._area_id}号数据链接') if self._waiting_pause is not None: print(f'暂停启动{self._area_id}号数据链接,等待RESUME指令') await self._waiting_pause async with self._conn_lock: if self._closed: break bili_statistics.rooms(+1) await self._prepare_client() if not await self._open(): bili_statistics.rooms(-1) continue tasks = [asyncio.ensure_future(i()) for i in self._funcs_task] self._task_main = asyncio.ensure_future(self._func_main_task()) tasks.append(self._task_main) _, pending = await asyncio.wait( tasks, return_when=asyncio.FIRST_COMPLETED) print(f'{self._area_id}号数据连接异常或主动断开,正在处理剩余信息') bili_statistics.rooms(-1) for i in tasks: if i != self._task_main and not i.done(): i.cancel() await self._close() if pending: await asyncio.wait(pending) print(f'{self._area_id}号数据连接退出,剩余任务处理完毕') self._waiting_end.set_result(True)
async def _verify_tcp_req(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> Receiver: conn = TcpReceiverConn(writer=writer, reader=reader) addr, _ = writer.get_extra_info('peername') if isinstance(addr, str) and self._blacklist.should_be_banned(addr): print(f'拒绝黑名单用户 IP {addr} 连接请求') self._blacklist.refresh(addr) raise tcp_req_exception.BanError(conn) json_data = await conn.recv_json() if json_data is not None and isinstance(json_data, dict) and 'data' in json_data: data = json_data['data'] if isinstance(data, dict) and 'key' in data: try: orig_key = str(data['key']) key_index = self._key_handler.verify_key(orig_key) print(f'来自 IP {addr}的用户 {key_index[:5]} 成功验证身份') return Receiver(user_conn=conn, user_key_index=key_index) except KeyCheckMaxError: print(f'IP {addr} 使用的 key 已连接用户过多') raise tcp_req_exception.MaxError(conn) except KeyCheckVerificationError: self._blacklist.refresh(addr) print(f'IP {addr} 错误尝试 key') raise tcp_req_exception.VerificationError(conn) except: raise tcp_req_exception.DataError(conn) raise tcp_req_exception.DataError(conn)
async def run_alert(self): if len(self.user.alerts) == 0: print('感谢🐔公告循环内容为空') return now = 0 while (1): if self.is_live: text = self.user.alerts[now % len(self.user.alerts)] await self.send_danmu(text) now += 1 else: print(f'{self._room_id}未开播, {datetime.datetime.now()}') await asyncio.sleep(self.user.alert_second)
async def auto_ban(self, username: str, uid: int, danmu: str): for r in self.user.ban: key = r.get('key') percent = float(r.get('percent', 1)) hour = int(r.get('hour', 720)) check = re.findall(key, danmu) if len(check) > 0 and len(check[0]) / len(danmu) >= percent: json_rsp = await self.user.req_s(BanUserReq.ban_user, self.user, self._room_id, uid, int(hour)) print(json_rsp) self.write_log(json.dumps(json_rsp, ensure_ascii=False)) return True
async def exec_task(self, task, *args, **kwargs): handle_check = None handle_works = None handle_work = None func_work = None handle_unique = None need_results = None if task.TASK_TYPE == TaskType.SCHED: handle_check = self.run_sched_func_with_return func_work = task.work need_results = False elif task.TASK_TYPE == TaskType.FORCED: handle_check = self.run_forced_func func_work = task.work need_results = False elif task.TASK_TYPE == TaskType.CONSOLE: handle_check = self.run_forced_func ctrl, *args = args # 此时ctrl隐含在args中 if ctrl == 'web': func_work = task.web_console_work need_results = True elif ctrl == 'cmd': func_work = task.cmd_console_work need_results = False if task.HOW2CALL == How2Call.DONT_WAIT: handle_works = self._dont_wait if task.TASK_TYPE == TaskType.SCHED: handle_work = self.run_sched_func_bg else: handle_work = self.run_forced_func_bg elif task.HOW2CALL == How2Call.WAIT: handle_works = self._wait handle_work = self.run_forced_func elif task.HOW2CALL == How2Call.WAIT_AND_PASS: handle_works = self._wait_and_pass handle_work = self.run_forced_func if task.UNIQUE_TYPE == UniqueType.MULTI: handle_unique = self._multi_work elif task.UNIQUE_TYPE == UniqueType.UNIQUE: handle_unique = self._unique_work check_results = await handle_check(task.check, self._users.superuser, *args, **kwargs) print('check_results:', task, check_results) if check_results is not None: return await handle_works(task, handle_work, handle_unique, func_work, check_results, need_results)
async def auto_reply(self, username: str, uid: int, danmu: str): # [{'key': '^.*(好听).*$', 'percent': 1, 'reply': '好听赶紧关注啊!'}] weight, height = await self.get_gamestr() for r in self.user.reply: key = r.get('key') percent = float(r.get('percent', 1)) reply = r.get('reply') check = re.findall(key, danmu) if len(check) > 0 and len(check[0]) / len(danmu) >= percent: print(check, danmu, percent, key) await self.send_danmu( reply.format(weight=weight, height=height)) return True
def handle_danmu(self, data: dict): raffle_type = data['raffle_type'] if raffle_type == 'STORM': raffle_id = data['raffle_id'] raffle_roomid = 0 print(f'{self._area_id}号弹幕监控检测到{raffle_roomid:^9}的节奏风暴(id: {raffle_id})') raffle_handler.exec_at_once(StormRaffleJoinTask, 0, raffle_id) bili_statistics.add2pushed_raffles('Yj协同节奏风暴', 2) elif raffle_type == 'GUARD': raffle_id = data['raffle_id'] raffle_roomid = data['room_id'] print(f'{self._area_id}号弹幕监控检测到{raffle_roomid:^9}的大航海(id: {raffle_id})') raffle_handler.push2queue(GuardRafflJoinTask, raffle_roomid, raffle_id) bili_statistics.add2pushed_raffles('Yj协同大航海', 2) return True
def parse_body(self, body: bytes, opt: int) -> bool: # 人气值(或者在线人数或者类似)以及心跳 if opt == Opt.HEARTBEAT_REPLY: pass # cmd elif opt == Opt.SEND_MSG_REPLY: if not self.handle_danmu(json.loads(body.decode('utf-8'))): return False # 握手确认 elif opt == Opt.AUTH_REPLY: print(f'{self._area_id} 号数据连接进入房间({self._room_id})') else: print('?????', body) return False return True
def handle_danmu(self, data: dict) -> bool: if 'cmd' in data: cmd = data['cmd'] elif 'msg' in data: data = data['msg'] cmd = data['cmd'] else: return True # 预防未来sbb站 if cmd == 'PREPARING': print(f'{self._area_id} 号数据连接房间下播({self._room_id})') return False elif cmd == 'NOTICE_MSG': # 1 《第五人格》哔哩哔哩直播预选赛六强诞生! # 2 全区广播:<%user_name%>送给<%user_name%>1个嗨翻全城,快来抽奖吧 # 3 <%user_name%> 在 <%user_name%> 的房间开通了总督并触发了抽奖,点击前往TA的房间去抽奖吧 # 4 欢迎 <%总督 user_name%> 登船 # 5 恭喜 <%user_name%> 获得大奖 <%23333x银瓜子%>, 感谢 <%user_name%> 的赠送 # 6 <%user_name%> 在直播间 <%529%> 使用了 <%20%> 倍节奏风暴,大家快去跟风领取奖励吧!(只报20的) msg_type = data['msg_type'] real_roomid = data['real_roomid'] msg_common = clear_whitespace(data['msg_common'], '“”') if msg_type == 2 or msg_type == 8: if data['msg_common']: # description0, raffle_name = self.NOTICE_MSG_TV_PATTERN.match(msg_common).group(1, 2) broadcast = 'nmb' raffle_num = 1 raffle_name = '小电视' # print(f'{self._area_id} 号数据连接检测到{real_roomid:^9}的{raffle_name}') raffle_handler.push2queue(TvRaffleJoinTask, real_roomid) broadcast_type = 0 if broadcast == '全区' else 1 bili_statistics.add2pushed_raffles(raffle_name, broadcast_type, raffle_num) elif msg_type == 3: raffle_name = self.NOTICE_MSG_GUARD_PATTERN.match( msg_common).group(1) # print(f'{self._area_id} 号数据连接检测到{real_roomid:^9}的{raffle_name}') raffle_handler.push2queue(GuardRafflJoinTask, real_roomid) broadcast_type = 0 if raffle_name == '总督' else 2 bili_statistics.add2pushed_raffles(raffle_name, broadcast_type) elif msg_type == 6: raffle_name = '二十倍节奏风暴' # print(f'{self._area_id} 号数据连接检测到{real_roomid:^9}的{raffle_name}') raffle_handler.push2queue(StormRaffleJoinTask, real_roomid) bili_statistics.add2pushed_raffles(raffle_name) return True
async def run_alter(self): if len(self.user.alerts) == 0: print('感谢🐔公告循环内容为空') return now = 0 while(1): json_rsp = await self.user.req_s(UtilsReq.init_room, self.user, self._room_id) status = json_rsp.get('data', {}).get('live_status') if status == 1: text = self.user.alerts[now % len(self.user.alerts)] await self.send_danmu(text) now += 1 else: print(f'{self._room_id}未开播, {datetime.datetime.now()}') await asyncio.sleep(self.user.alert_second)
async def one_try(): web_session = WebSession() bili = Bili(web_session) crack_client = CrackClient('http://127.0.0.1:3333', web_session) args = await bili.get_key() while True: url = await bili.login(*args, '', '', '') if url is not None: break print(f'url {url}') result = await crack_client.request_crack(url=url) print(f'request_crack result: {result}') if not result['code']: data = result['data'] await bili.login(*args, challenge=data['challenge'], seccode=data['seccode'], validate=data['validate']) await web_session.session.close()
def printSlotThreadOver(self, flag): print('Print Thread Over flag:', flag) logging.info('Print Thread Over flag:' + str(flag)) self.printPhaseCount += 1 if not flag: self.printPhaseErrCount += 1 if self.printPhaseCount == len(self.onlineDevices): if self.printPhaseErrCount == 0: QMessageBox.information(self.printButton, SUCCESSTITLE, PRINTER_OK_MSG) print("Print over.") else: QMessageBox.critical(self.printButton, ERRORTITLE, self.printPhaseErrCount + "pecs" + BURN_ERROR) self.printButton.setChecked(False) self.printButton.setDisabled(False)
def firstSlotThreadOver(self, flag): print('First Thread Over flag:', flag) logging.info('First Thread Over flag:' + str(flag)) self.firstPhaseCount += 1 if not flag: self.firstPhaseErrCount += 1 if self.firstPhaseCount == len(self.onlineDevices): if self.firstPhaseErrCount == 0: QMessageBox.information(self.firstRoundButton, SUCCESSTITLE, BURN_FIRST_ROUND_OK) logging.info("FirstRound flash over.") else: QMessageBox.critical(self.firstRoundButton,ERRORTITLE,self.firstPhaseErrCount + "pecs" + BURN_ERROR) self.firstRoundButton.setChecked(False) self.firstRoundButton.setDisabled(False)
async def post_raffle_handler(self, request: web.Request) -> web.StreamResponse: try: name, data = await self._verify_json_req( request, self._rsa_handler.verify_admin) except json_req_exceptions.JsonReqError as e: return web.json_response(e.RSP_SUGGESTED) self._posters.update(name) print(f'接收到抽奖{data}') if 'raffle_id' in data: raffle_id = int(data['raffle_id']) if self._duplicate_checker.add2checker(raffle_id): sending_json_data = {'code': 0, 'type': 'raffle', 'data': data} asyncio.ensure_future( self._broadcast_raffle(sending_json_data)) return web.json_response({'code': 0, 'type': '', 'data': {}})
def parse_body(self, body: bytes, opt: int) -> bool: # 人气值(或者在线人数或者类似)以及心跳 if opt == 3: # num_watching, = struct.unpack('!I', body) # print(f'弹幕心跳检测{self._area_id}') pass # cmd elif opt == 5: if not self.handle_danmu(json.loads(body.decode('utf-8'))): return False # 握手确认 elif opt == 8: print(f'{self._area_id}号弹幕监控进入房间({self._room_id})') else: print(body) return False return True
def handle_danmu(self, data: dict): cmd = data['cmd'] if cmd == 'SPECIAL_GIFT': if 'data' in data and '39' in data['data'] and data['data']['39'][ 'action'] == 'start': print(f'{self._area_id}号数据连接检测到{self._room_id:^9}的节奏风暴') raffle_handler.exec_at_once(StormRaffleJoinTask, self._room_id, data['data']['39']['id']) bili_statistics.add2pushed_raffles('节奏风暴', broadcast_type=2) elif cmd == 'NOTICE_MSG': msg_type = data['msg_type'] real_roomid = data['real_roomid'] msg_common = data['msg_common'].replace(' ', '') msg_common = msg_common.replace('”', '') msg_common = msg_common.replace('“', '') if msg_type == 3: raffle_name = msg_common.split('开通了')[-1][:2] if raffle_name != '总督': print( f'{self._area_id}号数据连接检测到{real_roomid:^9}的提督/舰长(API0)') raffle_handler.push2queue(GuardRafflJoinTask, real_roomid) bili_statistics.add2pushed_raffles('提督/舰长(API0)', broadcast_type=2) elif cmd == 'GUARD_MSG': if 'buy_type' in data and data['buy_type'] != 1: print(f'{self._area_id}号数据连接检测到{self._room_id:^9}的提督/舰长(API1)') raffle_handler.push2queue(GuardRafflJoinTask, self._room_id) bili_statistics.add2pushed_raffles('提督/舰长(API1)', broadcast_type=2) elif cmd == "USER_TOAST_MSG": if data['data']['guard_level'] != 1: print(f'{self._area_id}号数据连接检测到{self._room_id:^9}的提督/舰长(API2)') raffle_handler.push2queue(GuardRafflJoinTask, self._room_id) bili_statistics.add2pushed_raffles('提督/舰长(API2)', broadcast_type=2) elif cmd == "GUARD_BUY": if data['data']['guard_level'] != 1: print(f'{self._area_id}号数据连接检测到{self._room_id:^9}的提督/舰长(API3)') raffle_handler.push2queue(GuardRafflJoinTask, self._room_id) bili_statistics.add2pushed_raffles('提督/舰长(API3)', broadcast_type=2) return True
def secondSlotThreadOver(self, flag): print('Second Thread Over flag:', flag) logging.info('Second Thread Over flag:' + str(flag)) self.secondPhaseCount += 1 if not flag: self.secondPhaseErrCount += 1 if self.secondPhaseCount == len(self.onlineDevices): if self.secondPhaseErrCount == 0: QMessageBox.information(self.secondRoundButton, SUCCESSTITLE, BURN_SECOND_ROUND_OK) logging.info("SecondRound flash over.") else: QMessageBox.critical(self.secondRoundButton, ERRORTITLE, self.secondPhaseErrCount + "pecs" + BURN_ERROR) logging.error("SecondRound flash over error.") self.secondRoundButton.setChecked(False) self.secondRoundButton.setDisabled(False)
def handle_danmu(self, data: dict): if 'cmd' in data: cmd = data['cmd'] elif 'msg' in data: data = data['msg'] cmd = data['cmd'] else: return True # 预防未来sbb站 if cmd == 'PREPARING': print(f'{self._area_id}号数据连接房间PREPARING({self._room_id})') self.is_online = False return True elif cmd == 'LIVE': # print(f'{self._area_id}号数据连接房间开播LIVE({self._room_id})') self.is_online = True return True return super().handle_danmu(data)
def __req(self, parse_rsp, method, url, **kwargs): i = 0 while True: i += 1 if i >= 10: warn(f'反复请求多次未成功, {url}, {kwargs}') time.sleep(1) try: with self.__session.request(method, url, **kwargs) as rsp: if rsp.status_code == 200: body = parse_rsp(rsp) if body: # 有时候是 None 或空,直接屏蔽。read 或 text 类似,禁止返回空的东西 return body except requests.exceptions.RequestException as e: print(e) except Exception: # print('当前网络不好,正在重试,请反馈开发者!!!!') print(sys.exc_info()[0], sys.exc_info()[1], url)
async def unique(func, *args, **kwargs): user, *args = args if func in user.recording_tasks: status = user.recording_tasks[func] else: status = {} user.recording_tasks[func] = status if 'finish_time' not in status or status['finish_time']: status['finish_time'] = 0 # 0 表示开始且未完成 status['start_time'] = 1 try: result = await func(user, *args, **kwargs) status['finish_time'] = 1 # 1 表示结束 return result except asyncio.CancelledError: print(f'❌取消正在进行的{func}任务') status['finish_time'] = -1 # -1 表示取消了 else: print(f'重复推送{func}(此为debug信息忽略即可)') return None
def firstSlotThreadOver(self, flag): print('First Thread Over flag:', flag) logging.info('First Thread Over flag:' + str(flag)) self.firstPhaseCount += 1 if not flag: self.firstPhaseErrCount += 1 if self.firstPhaseCount == len(self.onlineDevices): if self.firstPhaseErrCount == 0: QMessageBox.information(self.firstRoundButton, SUCCESSTITLE, BURN_FIRST_ROUND_OK) logging.info("FirstRound flash over.") else: QMessageBox.critical( self.firstRoundButton, ERRORTITLE, self.firstPhaseErrCount + "pecs" + BURN_ERROR) self.firstRoundButton.setChecked(False) self.firstRoundButton.setDisabled(False)
def printSlotThreadOver(self, flag): print('Print Thread Over flag:', flag) logging.info('Print Thread Over flag:' + str(flag)) self.printPhaseCount += 1 if not flag: self.printPhaseErrCount += 1 if self.printPhaseCount == len(self.onlineDevices): if self.printPhaseErrCount == 0: QMessageBox.information(self.printButton, SUCCESSTITLE, PRINTER_OK_MSG) print("Print over.") else: QMessageBox.critical( self.printButton, ERRORTITLE, self.printPhaseErrCount + "pecs" + BURN_ERROR) self.printButton.setChecked(False) self.printButton.setDisabled(False)
def create_key(self, max_users: int, available_days: int) -> str: while True: orig_key = ''.join(random.choices(self._key_seed, k=16)) # 100^16 别想着暴力了,各位 hashed_key: str = self._ph.hash(orig_key) naive_hashed_key: str = utils.naive_hash(orig_key) if sql.is_key_addable(key_index=naive_hashed_key, key_value=hashed_key): key_created_time = 0 expired_time = 0 if not available_days else key_created_time + available_days * 3600 * 24 sql.insert_element( sql.Key(key_index=naive_hashed_key, key_value=hashed_key, key_created_time=key_created_time, key_max_users=max_users, key_expired_time=expired_time)) print( f'创建了一个新的KEY(MAX人数为{max_users:^5}人, 可用天数为{available_days:^5}天): {orig_key}' ) return orig_key
def verify_key(self, orig_key: str) -> str: key_index = utils.naive_hash(orig_key) key = sql.select_by_primary_key(key_index) # 非空且未过期 if key is not None and \ not (key.key_created_time and key.key_expired_time < utils.curr_time() and key.key_expired_time): try: self._ph.verify(key.key_value, orig_key) except VerifyMismatchError: raise KeyCheckVerificationError() if not key.key_created_time: print(f'正在激活 {key_index[:5]}***') sql.activate( key_index) # 只更新 creat 和 expire 时间,后面的返回不需要这么多东西,这里就不需要刷新了 if self._receivers.count_user_by_key( key.key_index) < key.key_max_users: # 连接数量限制 return key_index raise KeyCheckMaxError() raise KeyCheckVerificationError()
def secondSlotThreadOver(self, flag): print('Second Thread Over flag:', flag) logging.info('Second Thread Over flag:' + str(flag)) self.secondPhaseCount += 1 if not flag: self.secondPhaseErrCount += 1 if self.secondPhaseCount == len(self.onlineDevices): if self.secondPhaseErrCount == 0: QMessageBox.information(self.secondRoundButton, SUCCESSTITLE, BURN_SECOND_ROUND_OK) logging.info("SecondRound flash over.") else: QMessageBox.critical( self.secondRoundButton, ERRORTITLE, self.secondPhaseErrCount + "pecs" + BURN_ERROR) logging.error("SecondRound flash over error.") self.secondRoundButton.setChecked(False) self.secondRoundButton.setDisabled(False)
def parse_body(self, body: bytes, opt: int) -> bool: # 人气值(或者在线人数或者类似)以及心跳 if opt == 3: online_watchers_num, = self.online_struct.unpack(body) if self.online_watchers_num == -1: self.online_watchers_num = max(online_watchers_num, 5) elif online_watchers_num > self.online_watchers_num: self.online_watchers_num = online_watchers_num else: self.online_watchers_num = online_watchers_num * 0.35 + self.online_watchers_num * 0.65 # 延迟操作 if self.online_watchers_num <= 2.1 and not self.is_online: # 房间下播且人数很少的时候 print( f'{self._area_id}号数据连接房间下播({self._room_id},{online_watchers_num}, {self.online_watchers_num})' ) self.pause() return False # cmd elif opt == 5: if not self.handle_danmu(json.loads(body.decode('utf-8'))): return False # 握手确认 elif opt == 8: print(f'{self._area_id}号弹幕监控进入房间({self._room_id})') else: print(body) return False return True
async def _read_datas(self): while True: header = await self._conn.read_bytes(4) # 本函数对bytes进行相关操作,不特别声明,均为bytes if header is None: return len_body, = self.header_struct.unpack_from(header) # 心跳回复 if not len_body: print('yj,heartbeat') continue body = await self._conn.read_json(len_body) if body is None: return json_data = body data_type = json_data['type'] if data_type == 'raffle': if not self.handle_danmu(json_data['data']): return # 握手确认 elif data_type == 'entered': print(f'{self._area_id}号数据连接确认建立连接({self._key})') elif data_type == 'error': print(f'{self._area_id}号数据连接发生致命错误{json_data}') return
def firstRoundThreadTarget(self, device): print('FirstRoundThreadTarget' + device) # get socid temp,statusFlag = FastbootSoCID().getSoCID(deviceID=device) if statusFlag: self.secondRoundNeededSignal.emit(FASTBOOT_ERROR_SECONDROUND_NEEDED) FastbootLampCommand.setRedOn(deviceID=device) return for image in self.firstRoundList: logging.info(image['name']) if not os.path.exists(image['path']): self.imageNotFoundSignal.emit(IMAGEFILENOTFOUND) return if image['md5'] != CalcMD5().calcFileMd5(image['path']): self.checksumErrSignal.emit(CHECKSUM_ERROR) FastbootLampCommand.setRedOn(deviceID=device) return self.burnFlag = FastbootFlash().flashImage(deviceID=device, imageAddress=image['address'],imagePath=image['path']) if not self.burnFlag: print('FirstRound flash error first!' + image['name']) logging.error('FirstRound flash error first!' + image['name']) flagAgain = FastbootFlash().flashImage(deviceID=device, imageAddress=image['address'],imagePath=image['path']) if not flagAgain: print('FirstRound flash error secondly!' + image['name']) logging.error('FirstRound flash error secondly!' + image['name']) self.burnErrSignal.emit(BURN_ERROR) FastbootLampCommand.setRedOn(deviceID=device) return self.firstThreadEndSignal.emit(True)
async def run_forever(self): self._waiting = self._loop.create_future() while not self._closed: print(f'正在启动{self._area_id}号数据连接') async with self._conn_lock: if self._closed: break await self._prepare_client() if not await self._open(): continue tasks = [asyncio.ensure_future(i()) for i in self._funcs_task] self._task_main = asyncio.ensure_future(self._func_main_task()) tasks.append(self._task_main) _, pending = await asyncio.wait( tasks, return_when=asyncio.FIRST_COMPLETED) print(f'{self._area_id}号数据连接异常或主动断开,正在处理剩余信息') for i in tasks: if i != self._task_main and not i.done(): i.cancel() await self._close() if pending: await asyncio.wait(pending) print(f'{self._area_id}号数据连接退出,剩余任务处理完毕') self._waiting.set_result(True)
async def send_danmu(self, text, default_length=30, retry=1): # return if retry <= 0: return now = datetime.datetime.now() print(f'try to send length@{len(text)}/{default_length}: {text}') default_length = self.user.danmu_length msg = text[0:default_length] json_rsp = await self.user.req_s(UtilsReq.send_danmu, self.user, msg, self._room_id) print(f'[{now}]{json_rsp}') self.write_log(text) self.write_log(json.dumps(json_rsp, ensure_ascii=False)) # open(f'log/{self._room_id}-{now.year}{now.month:02d}{now.day:02d}.log', 'a').write(text + '\n') # open(f'log/{self._room_id}-{now.year}{now.month:02d}{now.day:02d}.log', 'a').write(json.dumps(json_rsp)+'\n') if json_rsp.get('msg', '') == 'msg in 1s': await asyncio.sleep(1) return await self.send_danmu(text, default_length, retry - 1) elif json_rsp.get('msg', '') == '': pass elif json_rsp.get('msg', '') in ['内容非法', 'f']: print(f'{text} --> 非法') # print(json_rsp) return # text = self.replace_num(text) # return await self.send_danmu(text, default_length, retry-1) elif json_rsp.get('msg', '') == 'msg repeat': return # await asyncio.sleep(0.5) # return await self.send_danmu(text, default_length, retry-3) elif json_rsp.get('msg', '') == '超出限制长度': print(f'{text} --> 超出长度') # print(text) # print(json_rsp) return await self.send_danmu(text, default_length - 10, retry) if len(text) > default_length: print(f'{text} --> 第二部分发出') await asyncio.sleep(1) await self.send_danmu(text[default_length:], default_length, retry)
async def check_result(self): while True: if self._waiting_pause is not None: print(f'暂停启动动态抽奖查找过期循环,等待RESUME指令') await self._waiting_pause results = dyn_raffle_sql.select_rafflestatus( 1, None, utils.curr_time() - 900) # 延迟15min处理抽奖 results += dyn_raffle_sql.select_rafflestatus( -1, None, utils.curr_time() - 900) print('正在查找已经结束的动态抽奖:', results) for dyn_raffle_status in results: dyn_raffle_results: Optional[ DynRaffleResults] = await notifier.exec_func( DynRaffleUtilsTask.fetch_dyn_raffle_results, dyn_raffle_status) print(dyn_raffle_status, dyn_raffle_results) await notifier.exec_task(DynRaffleNoticeTask, dyn_raffle_status, dyn_raffle_results) if dyn_raffle_results is not None: dyn_raffle_sql.insert_dynraffle_results_table( dyn_raffle_results) dyn_raffle_sql.del_from_dynraffle_status_table( dyn_raffle_status.dyn_id) await asyncio.sleep(120)
async def check_result(self): while True: if self._waiting_pause is not None: print(f'暂停启动实物抽奖查找过期循环,等待RESUME指令') await self._waiting_pause results = substance_raffle_sql.select_rafflestatus( 1, None, utils.curr_time() - 900) # 延迟15min处理抽奖 results += substance_raffle_sql.select_rafflestatus( -1, None, utils.curr_time() - 900) print('正在查找已经结束的实物抽奖:', results) for substance_raffle_status in results: substance_raffle_results: Optional[ SubstanceRaffleResults] = await notifier.exec_func( SubstanceRaffleUtilsTask. fetch_substance_raffle_results, substance_raffle_status) print(substance_raffle_status, substance_raffle_results) await notifier.exec_task(SubstanceRaffleNoticeTask, substance_raffle_status, substance_raffle_results) if substance_raffle_results is not None: substance_raffle_sql.insert_substanceraffle_results_table( substance_raffle_results) substance_raffle_sql.del_from_substanceraffle_status_table( substance_raffle_status.aid, substance_raffle_status.number) await asyncio.sleep(30)
async def exec_forced_task(self, task, *args, **kwargs): check_results = await self.run_forced_func(self._users.superuser, task.check, *args, **kwargs) print('check_results:', task, check_results) if check_results is None: return for user_id, delay_range, *args in check_results: if delay_range is not None: for user in self._users.gets(user_id): delay = random.uniform(*delay_range) self._loop.call_later(delay, self.run_forced_func_bg, user, task.work, *args) else: # 这里是特殊处理为None的时候,去依次执行,且wait untill all done result = None for user in self._users.gets(user_id): if result is None: result = await self.run_forced_func( user, task.work, *args) else: # 不为None表示每个用户之间参数互传 result = await self.run_forced_func( user, task.work, *args, result) return result
def printerThreadTarget(self,device): print('printerThreadTarget' + device) # get mac macAddr0 = FastbootMACCommand().getMAC(deviceID=device) logging.info(macAddr0) if len(macAddr0) == 0: self.burnNeededSignal.emit(PRINTER_BURN_NEEDED_MSG) return mac = ''.join(macAddr0.split(':')) print(mac) # get sn sn,statusFlag = FastbootSoCID().getSoCID(deviceID=device) if not len(sn): self.socIDErrSignal.emit(FASTBOOT_ERROR_GET_SOCID) FastbootLampCommand.setRedOn(deviceID=device) return print(sn) mysql = MySQLCommand(host=self.sysXMLDict['mysqlhost'],port=int(self.sysXMLDict['mysqlport']),user=self.sysXMLDict['mysqluser'],\ passwd=self.sysXMLDict['mysqlpassword'],db=self.sysXMLDict['mysqldatabase'],table=self.sysXMLDict['mysqltable']) mysqlConFlag = mysql.connectMysql() if not mysqlConFlag: FastbootLampCommand.setRedOn(deviceID=device) self.mysqlConnectErrSignal.emit(MYSQL_CONNECT_ERROR) return self.lock.acquire() snInDb = mysql.queryMysqlSNByMAC(mac=mac,stbType=self.sysXMLDict['mysqlstbtype'],poNumber=self.poNumber) if not snInDb: self.getSnErrSignal.emit(FASTBOOT_ERROR_GET_SERIALNUMBER) mysql.closeMysql() self.lock.release() FastbootLampCommand.setRedOn(deviceID=device) return elif sn != snInDb: self.printSNNotEqualInDBSignal.emit(PRINTER_SN_NOT_EQUAL_TO_DB) mysql.closeMysql() self.lock.release() FastbootLampCommand.setRedOn(deviceID=device) logging.error('sn local is not equal to sn in db.') return else: printFlag = MacSNPrint.sendInfoToPrinter(host=self.sysXMLDict['printerhost'],port=int(self.sysXMLDict['printerport']),sn=sn,mac=mac) if not printFlag: self.printMACSNErrSignal.emit(PRINTER_ERROR_MSG) FastbootLampCommand.setRedOn(deviceID=device) else: FastbootLampCommand.setGreenOn(deviceID=device) mysql.closeMysql() self.lock.release()
def deleteTocDir(self,dirPath): try: shutil.rmtree(dirPath) except: print('Delete sysinfo toc failed.') logging.error("Delete sysinfo toc failed.")
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) self.checkFastbootTool() self.actionExit.triggered.connect(self.close) self.actionCopy.triggered.connect(self.onCopyTriggered) self.actionPaste.triggered.connect(self.onPasteTriggered) self.actionCut.triggered.connect(self.onCutTriggered) self.actionHelp.triggered.connect(self.onHelpTriggered) self.actionAbout.triggered.connect(self.onAboutTriggered) # self.action_backupDB.triggered.connect(self.onBackupDBTriggered) # self.action_reset_mac.triggered.connect(self.onResetMACTriggered) self.firstRoundButton.clicked.connect(self.onFirstRoundClicked) self.secondRoundButton.clicked.connect(self.onSecondRoundClicked) self.printButton.clicked.connect(self.onPrinterClicked) self.firstRoundList = [] self.secondRoundList = [] self.sysXMLDict = {} self.onlineDevices = [] self.firstRoundList,self.secondRoundList = self.parseXMLFile(CONFIGXML) self.sysXMLDict = self.parseSYSXMLFile(CONFIGSYSXML) logging.info(self.sysXMLDict) print('burnTool version:') print(self.sysXMLDict['version']) print(self.firstRoundList) print(self.secondRoundList) logging.info(self.firstRoundList) logging.info(self.secondRoundList) self.firstPhaseCount = 0 self.firstPhaseErrCount = 0 self.secondPhaseCount = 0 self.secondPhaseErrCount = 0 self.printPhaseCount = 0 self.printPhaseErrCount = 0 self.poNumber = '' self.showPONInputDialog() self.burnFlag = False self.lock = RLock() self.checksumErrSignal.connect(self.slotShowMessage) self.burnErrSignal.connect(self.slotShowMessage) self.socIDErrSignal.connect(self.slotShowMessage) self.cpcbErrSignal.connect(self.slotShowMessage) self.getMacErrSignal.connect(self.slotShowMessage) self.firstRoundNeededSignal.connect(self.slotShowMessage) self.secondRoundNeededSignal.connect(self.slotShowMessage) self.updateMysqlErrSignal.connect(self.slotShowMessage) self.resetMysqlErrSignal.connect(self.slotShowMessage) self.imageNotFoundSignal.connect(self.slotShowMessage) self.irdetoKeyErrSignal.connect(self.slotShowMessage) self.mysqlConnectErrSignal.connect(self.slotShowMessage) self.burnNeededSignal.connect(self.slotShowMessage) self.getSnErrSignal.connect(self.slotShowMessage) self.printMACSNErrSignal.connect(self.slotShowMessage) self.printSNNotEqualInDBSignal.connect(self.slotShowMessage) self.secondThreadEndSignal.connect(self.secondSlotThreadOver) self.firstThreadEndSignal.connect(self.firstSlotThreadOver) self.printThreadEndSignal.connect(self.printSlotThreadOver) self.timerDevice = QTimer(self) self.timerMAC = QTimer(self) self.timerDevice.timeout.connect(self.showCurrentDevices) if(self.sysXMLDict['isNeedToConnectMysql'] == 'yes'): self.timerMAC.timeout.connect(self.showCurrentAvailableMAC) self.timerMAC.start(MYSQL_SHOW_AVAILABLE_MAC_COUNT_TIMEOUT) elif(self.sysXMLDict['isNeedToConnectMysql'] == 'no'): pass self.startCount()
def secondRoundThreadTarget(self,device,imageTurple): print('SecondRoundThreadTarget:' + device) FastbootLampCommand.setRedFast(deviceID=device) needCalcCPCBFlag = False dictionary = {} secondModifyList = [] secondModifyList = list(imageTurple) # 不带冒号MAC macAddr0 = '' # get socid socid,statusFlag = FastbootSoCID().getSoCID(deviceID=device) if not statusFlag: self.firstRoundNeededSignal.emit(FASTBOOT_ERROR_FIRSTROUND_NEEDED) return if not len(socid): self.socIDErrSignal.emit(FASTBOOT_ERROR_GET_SOCID) FastbootLampCommand.setRedOn(deviceID=device) return for image in secondModifyList: if not os.path.exists(image['path']): self.imageNotFoundSignal.emit(IMAGEFILENOTFOUND) return if image['address'] == 'iploader': needCalcCPCBFlag = True # socidFormat = self.socIDFormatter(socid) socidFormat = str(socid) logging.info('\r\n') logging.info('socid: ' + socidFormat) # get serial number serialNumber = str(socidFormat[3:]) logging.info('serial number: ' + serialNumber) mysql = MySQLCommand(host=self.sysXMLDict['mysqlhost'],port=int(self.sysXMLDict['mysqlport']),user=self.sysXMLDict['mysqluser'],\ passwd=self.sysXMLDict['mysqlpassword'],db=self.sysXMLDict['mysqldatabase'],table=self.sysXMLDict['mysqltable']) mysqlConFlag = mysql.connectMysql() if not mysqlConFlag: FastbootLampCommand.setRedOn(deviceID=device) self.mysqlConnectErrSignal.emit(MYSQL_CONNECT_ERROR) return self.lock.acquire() macFormat = FastbootMACCommand.getMAC(deviceID=device) logging.info('local mac:' + str(macFormat)) print('local mac:',macFormat) snExistFlag = mysql.queryMysqlSN(sn=socidFormat,mac=self.macFormatter(macFormat),stbType=self.sysXMLDict['mysqlstbtype'],poNumber=self.poNumber) if not snExistFlag: # 序列号 and mac不在数据库中 mac = mysql.queryMysql(stbType=self.sysXMLDict['mysqlstbtype'],poNumber=self.poNumber) print('get mac from db=',mac) logging.info('get mac from db=' + str(mac)) if not mac: self.getMacErrSignal.emit(FASTBOOT_ERROR_GET_MAC) mysql.closeMysql() self.lock.release() FastbootLampCommand.setRedOn(deviceID=device) return else: macAddr0 = mac updateFlag = mysql.updateMysqlSN(mac=mac,sn=socidFormat,stbType=self.sysXMLDict['mysqlstbtype'],poNumber=self.poNumber) if not updateFlag: print("Update mysql serialnum failed.") logging.error("Update mysql serialnum failed.") mysql.closeMysql() self.lock.release() self.updateMysqlErrSignal.emit(FASTBOOT_ERROR_RESET_MAC_STATUS) FastbootLampCommand.setRedOn(deviceID=device) self.resetMysqlMACStatus(mac=mac) return else: dictionary['STB_MAC'] = str(macAddr0[0:2] + ':' + macAddr0[2:4] + ':' + macAddr0[4:6] + ':' + macAddr0[6:8] + ':' + macAddr0[8:10] + ':' + macAddr0[10:12]) else: # 已经是烧录过的盒子,使用已有MAC,macFormat带冒号 # macFormat = FastbootMACCommand.getMAC(deviceID=device) dictionary['STB_MAC'] = str(macFormat) print('burned stb MAC=') print(macFormat) logging.info('burned stb MAC=') logging.info(macFormat) mysql.closeMysql() self.lock.release() randomNum = IrdKeyOP.getRandomNumber() # print("random number:" + randomNum) logging.info("random number:" + randomNum) dictionary['BOOT_METHOD'] = 'normal' # 检查包中是否有factorytest.img镜像 for imgList in secondModifyList: if imgList['name'] == 'factorytest.img' and imgList['address'] == 'otaloaderbak': dictionary['BOOT_METHOD'] = '0x98' break # generater sysinfo dictionary['STB_CA_KEY'] = str(socidFormat) dictionary['STB_ID'] = str(socidFormat) dictionary['IRDETO_SECURE_CHIP_SN'] = str(serialNumber) dictionary['IRDETO_RANDOM_NUMBER'] = str(randomNum) self.generateSysinfoImage(dictionary) # get IrdetoKey irdetoKeyFlag = IrdKeyOP.getKey(path='soc' + socidFormat,serialNum=serialNumber,randomNum=randomNum,keyType=int(self.sysXMLDict['irdetokeytype'])) if not irdetoKeyFlag: self.irdetoKeyErrSignal.emit(IRDETO_GET_KEY_ERROR) FastbootLampCommand.setRedOn(deviceID=device) self.resetMysqlMACAndSN(mac=self.macFormatter(dictionary['STB_MAC'])) return dict_ro = {} dict_rw = {} dict_cadata = {} dict_ro['name'] = 'systeminfo_ro' dict_ro['address'] = 'systeminfo_ro' dict_ro['path'] = 'soc' + socidFormat + '/' + 'systeminfo_ro.img' dict_ro['md5'] = '' dict_rw['name'] = 'systeminfo_rw' dict_rw['address'] = 'systeminfo_rw' dict_rw['path'] = 'soc' + socidFormat + '/' + 'systeminfo_rw.img' dict_rw['md5'] = '' dict_cadata['name'] = 'cadata' dict_cadata['address'] = 'cadata' dict_cadata['path'] = 'soc' + socidFormat + '/' + IRDETO_CADATA_FILE dict_cadata['md5'] = '' if not dict_rw in secondModifyList: secondModifyList.append(dict_rw) if not dict_cadata in secondModifyList: secondModifyList.append(dict_cadata) if not dict_ro in secondModifyList: secondModifyList.append(dict_ro) print(secondModifyList) logging.info(secondModifyList) for image in secondModifyList: logging.info(image['name']) if image['address'] != 'systeminfo_ro' and image['address'] != 'systeminfo_rw' and image['address'] != 'cadata': if image['md5'] != CalcMD5().calcFileMd5(image['path']): self.checksumErrSignal.emit(CHECKSUM_ERROR) FastbootLampCommand.setRedOn(deviceID=device) secondModifyList.remove(dict_ro) secondModifyList.remove(dict_rw) self.deleteTocDir('soc' + socidFormat) self.resetMysqlMACAndSN(mac=self.macFormatter(dictionary['STB_MAC'])) return self.burnFlag = FastbootFlash().flashImage(deviceID=device, imageAddress=image['address'],imagePath=image['path']) if not self.burnFlag: print('SecondRound flash error!' + image['name'] + 'soc:' + socidFormat) logging.error('SecondRound flash error!' + image['name'] + 'soc:' + socidFormat) self.burnErrSignal.emit(BURN_ERROR) FastbootLampCommand.setRedOn(deviceID=device) secondModifyList.remove(dict_ro) secondModifyList.remove(dict_rw) self.deleteTocDir('soc' + socidFormat) self.resetMysqlMACAndSN(mac=self.macFormatter(dictionary['STB_MAC'])) if not FastbootFlash.erasePartition(deviceID=device, partition='systeminfo_ro'): print('erase systeminfo_ro failed.') logging.error('erase systeminfo_ro failed.') return if dict_ro in secondModifyList: secondModifyList.remove(dict_ro) if dict_rw in secondModifyList: secondModifyList.remove(dict_rw) if dict_cadata in secondModifyList: secondModifyList.remove(dict_cadata) self.deleteTocDir('soc' + socidFormat) # uboot cacl CPCB if needCalcCPCBFlag: print('start to calc cpcb.') logging.info('start to cacl cpcb.') self.burnFlag = FastbootCalcCPCB.calcCPCB(deviceID=device) if not self.burnFlag: print('calc cpcb error.') logging.error('calc cpcb error.') self.cpcbErrSignal.emit(FASTBOOT_ERROR_CALC_CPCB) FastbootLampCommand.setRedOn(deviceID=device) self.resetMysqlMACAndSN(mac=self.macFormatter(dictionary['STB_MAC'])) if not FastbootFlash.erasePartition(deviceID=device, partition='systeminfo_ro'): print('erase systeminfo_ro failed.') logging.error('erase systeminfo_ro failed.') return FastbootLampCommand.setGreenOn(deviceID=device) self.secondThreadEndSignal.emit(True)