async def dig_and_filter(self, dyn_raffle_status: DynRaffleStatus): doc_id = dyn_raffle_status.doc_id if dyn_raffle_status.lottery_time <= utils.curr_time() + 180: print(f'{doc_id}的动态抽奖已经开奖或马上开奖,不再参与') return for key_word in self.dyn_raffle_description_filter: if key_word in dyn_raffle_status.describe: print(f'{doc_id}的动态抽奖正文触发关键词过滤({key_word})') return for key_word in self.dyn_prize_cmt_filter: if key_word in dyn_raffle_status.prize_cmt_1st or \ key_word in dyn_raffle_status.prize_cmt_2nd or \ key_word in dyn_raffle_status.prize_cmt_3rd: print(f'{doc_id}的动态抽奖正文触发关键词过滤({key_word})') return # 如果是刚刚出来的抽奖,就延迟150秒, if dyn_raffle_status.post_time >= utils.curr_time() - 150: print(f'{doc_id}的动态抽奖触发时间约束,休眠150秒后再正式参与') await asyncio.sleep(150) if dyn_raffle_sql.is_raffleid_duplicate(dyn_raffle_status.dyn_id): print(f'{dyn_raffle_status.doc_id}的动态抽奖触发重复性过滤') return dyn_raffle_sql.insert_dynraffle_status_table(dyn_raffle_status) print(f'{doc_id}的动态抽奖通过过滤与验证,正式处理') if not self.should_join_immediately: print(f'{dyn_raffle_status.doc_id}的动态抽奖暂不参与,仅记录数据库中等候轮询') return print(f'{doc_id}的动态抽奖正在参与') await notifier.exec_task(DynRaffleJoinTask, dyn_raffle_status) dyn_raffle_sql.set_rafflestatus_handle_status(1, dyn_raffle_status.dyn_id) print(f'{doc_id}的动态抽奖参与完毕')
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 dig_and_filter(self, doc_id: int, uid: int, post_time: int, describe: str): dyn_raffle_status: DynRaffleStatus = await notifier.exec_func( -1, DynRaffleHandlerTask.fetch_dyn_raffle_status, doc_id, uid, post_time, describe) if dyn_raffle_status.lottery_time <= utils.curr_time() + 60: printer.info([f'{doc_id}的动态抽奖已经开奖或马上开奖,不再参与'], True) return for key_word in self.dyn_raffle_description_filter: if key_word in dyn_raffle_status.describe: printer.info([f'{doc_id}的动态抽奖正文触发关键词过滤({key_word})'], True) return for key_word in self.dyn_prize_cmt_filter: if key_word in dyn_raffle_status.prize_cmt_1st or \ key_word in dyn_raffle_status.prize_cmt_2nd or \ key_word in dyn_raffle_status.prize_cmt_3rd: printer.info([f'{doc_id}的动态抽奖正文触发关键词过滤({key_word})'], True) return # 如果是刚刚出来的抽奖,就延迟150秒, if dyn_raffle_status.post_time >= utils.curr_time() - 150: printer.info([f'{doc_id}的动态抽奖触发时间约束,休眠150秒后再正式参与'], True) await asyncio.sleep(150) printer.info([f'{doc_id}的动态抽奖通过时间和关键词过滤'], True) notifier.exec_task(-1, DynRaffleHandlerTask, 0, dyn_raffle_status, delay_range=(0, 0))
async def check_result(self): while True: 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) printer.infos(['正在查找已经结束的动态抽奖:', results]) for dyn_raffle_status in results: dyn_raffle_results: Optional[ DynRaffleResults] = await notifier.exec_func( -1, DynRaffleHandlerTask.fetch_dyn_raffle_results, dyn_raffle_status) print(dyn_raffle_status, dyn_raffle_results) await notifier.exec_task_awaitable(-2, DynRaffleHandlerTask, 2, dyn_raffle_status, dyn_raffle_results, delay_range=(0, 30)) 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: 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) printer.info(['正在查找已经结束的实物抽奖:', results], True) for substance_raffle_status in results: substance_raffle_results: Optional[ SubstanceRaffleResults] = await notifier.exec_func( -1, SubstanceRaffleHandlerTask. fetch_substance_raffle_results, substance_raffle_status) print(substance_raffle_status, substance_raffle_results) await notifier.exec_task_awaitable(-2, SubstanceRaffleHandlerTask, 2, substance_raffle_status, substance_raffle_results, delay_range=(0, 30)) 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)
def update(self, raffle_type: str): if raffle_type == 'GUARD': self.latest_guard_time = utils.curr_time() if raffle_type == 'TV': self.latest_tv_time = utils.curr_time() if raffle_type == 'STORM': self.latest_storm_time = utils.curr_time()
async def run_forever(self): self._waiting = self._loop.create_future() time_now = 0 while not self._closed: if utils.curr_time() - time_now <= 3: printer.info([f'网络波动,{self._area_id}号弹幕姬延迟3秒后重启'], True) await asyncio.sleep(3) printer.info([f'正在启动{self._area_id}号弹幕姬'], True) time_now = utils.curr_time() async with self._conn_lock: if self._closed: break if not await self._open_conn(): continue self._task_main = asyncio.ensure_future(self._read_datas()) task_heartbeat = asyncio.ensure_future(self._heart_beat()) tasks = [self._task_main, task_heartbeat] _, pending = await asyncio.wait( tasks, return_when=asyncio.FIRST_COMPLETED) printer.info([f'{self._area_id}号弹幕姬异常或主动断开,正在处理剩余信息'], True) if not task_heartbeat.done(): task_heartbeat.cancel() await self._close_conn() await asyncio.wait(pending) printer.info([f'{self._area_id}号弹幕姬退出,剩余任务处理完毕'], True) self._waiting.set_result(True)
async def join(user, real_roomid, raffleid, raffle_type, raffle_end_time): # print('参与', raffleid) # await UtilsTask.enter_room(user, real_roomid) json_response2 = await user.req_s(TvRaffleHandlerReq.join, user, real_roomid, raffleid) bili_statistics.add2joined_raffles('小电视(合计)', user.id) user.info([f'参与了房间{real_roomid:^9}的小电视抽奖'], True) user.info([f'# 小电视抽奖状态: {json_response2["msg"]}']) # -400不存在 # -500繁忙 code = json_response2['code'] if not code: sleeptime = raffle_end_time - utils.curr_time( ) + 5 # 小于0,call_later自动置0 return (2, (sleeptime, sleeptime + 90), user.id, raffleid, real_roomid), elif code == -500: print('# -500繁忙,稍后重试') return () elif code == 400: user.fall_in_jail() return () else: print(json_response2) return ()
async def check(user, real_roomid, try_times=10): for i in range(try_times): json_rsp = await user.req_s(GuardRaffleHandlerReq.check, user, real_roomid) # print(json_rsp) if json_rsp['data'] and (try_times == 1 or i >= try_times / 2): break await asyncio.sleep(1.7) else: print(f'{real_roomid}没有guard或者guard已经领取') return next_step_settings = [] data = json_rsp['data'] for j in data: raffle_id = j['id'] # 总督长达一天,额外处理 max_wait = j['time'] privilege_type = j['privilege_type'] if privilege_type != 1 and max_wait >= 100 \ and (not bili_statistics.is_raffleid_duplicate(raffle_id)): print('本次获取到的抽奖id为', raffle_id) raffle_data = { 'raffle_id': raffle_id, 'room_id': real_roomid, 'raffle_type': 'GUARD', 'end_time': max_wait + utils.curr_time() } next_step_setting = (-2, (0, 0), raffle_data) next_step_settings.append(next_step_setting) bili_statistics.add2raffle_ids(raffle_id) return next_step_settings
async def refresh_token(user): dict_cookie = dict() for param in user.dict_user['cookie'].split(';'): key, value = param.split('=') dict_cookie[key] = value extra_params = { 'access_key': user.dict_user['access_key'], 'access_token': user.dict_user['access_key'], 'refresh_token': user.dict_user['refresh_token'], 'ts': utils.curr_time(), **dict_cookie } params = user.app_sign(extra_params) # 这里没办法,cookie 里面有特殊字符,与 yarl 兼容无关 params_str = utils.prepare_params(params) url = f'https://passport.bilibili.com/api/v2/oauth2/refresh_token?{params_str}' json_rsp = await user.login_session.request_json( 'POST', url, headers=user.app.headers, params=None, ctrl=LOGIN_CTRL) print('json_rsp', json_rsp) return json_rsp
async def check_handle(self): while True: if self._waiting_pause is not None: print(f'暂停启动实物抽奖查找参与循环,等待RESUME指令') await self._waiting_pause curr_time = utils.curr_time() results = substance_raffle_sql.select_rafflestatus( -1, (curr_time - 45, curr_time + 90))[:5] print('正在查找需要参与的实物抽奖:', results) for substance_raffle_status in results: print(substance_raffle_status) aid = substance_raffle_status.aid number = substance_raffle_status.number is_exist = await notifier.exec_func( SubstanceRaffleUtilsTask.check, aid) if not is_exist: substance_raffle_sql.del_from_substanceraffle_status_table( aid, number) printer.warn(f'{substance_raffle_status}消失了。。。。。') continue print(f'{aid}({number})的实物抽奖正在参与') await notifier.exec_task(SubstanceRaffleJoinTask, substance_raffle_status) substance_raffle_sql.set_rafflestatus_handle_status( 1, aid, number) print(f'{aid}({number})的实物抽奖参与完毕') if not results: await asyncio.sleep(60)
async def work(user, dyn_raffle_status: DynRaffleStatus): if dyn_raffle_status.lottery_time - utils.curr_time() < 15: user.info(f'动态{dyn_raffle_status.dyn_id}马上或已经开奖,放弃参与') async with user.repost_del_lock: if dyn_raffle_status.feed_limit: # 关注 await DynRaffleJoinTask.follow_raffle_organizer( user, dyn_raffle_status.uid) # 创建动态并提交数据库 if await DynRaffleJoinTask.repost_dyn_raffle( user, dyn_raffle_status.dyn_id, dyn_raffle_status.at_num): user.info(f'转发参与动态{dyn_raffle_status.dyn_id}成功') for i in range(5): # 经常不能及时刷新 await asyncio.sleep(3) dyn_id = await DynRaffleJoinTask.fetch_reposted_dynid( user, user.dict_bili['uid'], dyn_raffle_status.dyn_id) if dyn_id is not None: user.info( f'查找转发动态{dyn_raffle_status.dyn_id}生成{dyn_id}') dyn_raffle_joined = DynRaffleJoined( dyn_id=dyn_id, orig_dynid=dyn_raffle_status.dyn_id, uid=user.dict_bili['uid']) print(dyn_raffle_joined) dyn_raffle_sql.insert_dynraffle_joined_table( dyn_raffle_joined) return user.warn(f'查找转发动态{dyn_raffle_status.dyn_id}生成失败') else: user.warn(f'转发参与动态{dyn_raffle_status.dyn_id}失败') return
async def check_result(self): while True: results = dyn_raffle_sql.select_bytime(utils.curr_time() + 900) # 延迟15min处理抽奖 for dyn_raffle_status in results: dyn_raffle_results: Optional[ DynRaffleResults] = await notifier.exec_func( -1, DynRaffleHandlerTask.fetch_dyn_raffle_results, dyn_raffle_status) print(dyn_raffle_status, dyn_raffle_results) future = asyncio.Future() notifier.exec_task(-1, DynRaffleHandlerTask, 2, dyn_raffle_status, dyn_raffle_results, future, delay_range=(0, 30)) await future if dyn_raffle_results is not None: dyn_raffle_sql.insert_dynraffle_results_table( dyn_raffle_results) print('Dnone') await asyncio.sleep(3600)
async def check_handler(self, request): try: sql.select_and_check() _, data = await self._verify_json_req(request, self._admin_pubkey) search_results = {} if 'naive_hashed_key' in data: key = sql.select_by_primary_key(data['naive_hashed_key']) result = key.as_str() if key is not None else '404' search_results['key_searched_by_naive_hash'] = result return web.json_response({ 'code': 0, 'type': 'server_status', 'data': { 'version': '0.1.2', 'observers_num': f'当前用户共{self._broadcaster.num_observers()}', # 'observers_count': self._broadcaster.count(), 'posters_count': self._post_office.count(), 'curr_db': '', 'search_results': search_results, 'curr_time': utils.curr_time(), 'encrypted_msg2admin': [], # 管理员信息需要私钥解密 'encrypted_msg2super_admin': [] # 超管信息需要超管私钥解密 } }) except json_req_exceptions.JsonReqError as e: return web.json_response(e.RSP_SUGGESTED)
async def dig_and_filter(self, substance_raffle_status: SubstanceRaffleStatus): aid = substance_raffle_status.aid number = substance_raffle_status.number if substance_raffle_status.join_end_time <= utils.curr_time() + 90: printer.info([f'{aid}({number})的实物抽奖已经开奖或马上开奖,不再参与/记录'], True) return for key_word in self.substance_raffle_description_filter: if key_word in substance_raffle_status.describe: printer.info([f'{aid}({number})的实物抽奖正文触发关键词过滤({key_word})'], True) return if substance_raffle_sql.is_raffleid_duplicate(aid, number): printer.info([f'{aid}({number})的实物抽奖触发重复性过滤'], True) return substance_raffle_sql.insert_substanceraffle_status_table( substance_raffle_status) printer.info([f'{aid}({number})的实物抽奖通过过滤与验证,正式处理'], True) assert not self.should_join_immediately if not self.should_join_immediately: printer.info([f'{aid}({number})的实物抽奖暂不参与,仅记录数据库中等候轮询'], True) return
async def check_handle(self): while True: curr_time = utils.curr_time() results = substance_raffle_sql.select_rafflestatus( -1, (curr_time - 45, curr_time + 90))[:5] printer.info(['正在查找需要参与的实物抽奖:', results], True) for substance_raffle_status in results: print(substance_raffle_status) aid = substance_raffle_status.aid number = substance_raffle_status.number is_exist = await notifier.exec_func( -1, SubstanceRaffleHandlerTask.check, aid) if not is_exist: substance_raffle_sql.del_from_substanceraffle_status_table( aid, number) printer.warn(f'{substance_raffle_status}消失了。。。。。') continue printer.info([f'{aid}({number})的实物抽奖正在参与'], True) await notifier.exec_task_awaitable(-2, SubstanceRaffleHandlerTask, 1, substance_raffle_status) substance_raffle_sql.set_rafflestatus_handle_status( 1, aid, number) printer.info([f'{aid}({number})的实物抽奖参与完毕'], True) if not results: await asyncio.sleep(60)
async def check(user, real_roomid, raffle_id=None): if raffle_id is not None: json_response = {'data': [{'id': raffle_id, 'time': 110}]} else: json_response = await user.req_s(PkRaffleHandlerReq.check, user, real_roomid) # print(json_response['data']['list']) list_raffles = json_response['data'] if not list_raffles: # sb可能返回None return None next_step_settings = [] for raffle in list_raffles: raffle_id = raffle['id'] max_wait = raffle['time'] # 处理一些重复 if not bili_statistics.is_raffleid_duplicate(raffle_id): raffle_data = { 'raffle_id': raffle_id, 'room_id': real_roomid, 'raffle_type': 'PK', 'end_time': utils.curr_time() + max_wait } next_step_setting = (-2, (0, 0), raffle_data) next_step_settings.append(next_step_setting) bili_statistics.add2raffle_ids(raffle_id) return next_step_settings
async def check_handler(self, request: web.Request) -> web.StreamResponse: try: _, data = await self._verify_json_req( request, self._rsa_handler.verify_super_admin) except json_req_exceptions.JsonReqError as e: return web.json_response(e.RSP_SUGGESTED) search_results = {} if 'naive_hashed_key' in data: result = self._key_handler.check_key_by_hashed_key( data['naive_hashed_key']) search_results['key_searched_by_naive_hash'] = result if 'check_ip' in data: search_results['is_ip_banned'] = self._blacklist.should_be_banned( data['check_ip']) if 'clean_ip' in data: self._blacklist.del_record(data['clean_ip']) search_results['is_ip_cleaned'] = True return web.json_response({ 'code': 0, 'type': '', 'data': { 'version': '0.2.1b1', 'observers_num': f'当前用户共{self._receivers.num_observers()}', 'posters_count': self._posters.count(), 'search_results': search_results, 'curr_time': utils.curr_time(), } })
async def login(user, url_name, url_password, captcha=''): validate = '' challenge = '' extra_params = { 'seccode': f'{validate}|jordan' if validate else '', 'validate': validate, 'challenge': challenge, 'username': url_name, 'password': url_password, 'ts': utils.curr_time(), } params = user.app_sign(extra_params) # url_password 存在一些 % 这些,b站要求作为 string 不编码为 "%25" # aiohttp doc 符合,但是 # https://github.com/aio-libs/aiohttp/blob/10c8ce9567d008d4f92a99ffe45f8d0878e99275/aiohttp/client_reqrep.py#L215-L219 # yarl 兼容问题 # 故手动处理 params_str = utils.prepare_params(params) url_aiohttp = f'https://passport.bilibili.com/x/passport-login/oauth2/login?{params_str}' json_rsp = await user.login_session.request_json( 'POST', url_aiohttp, headers=user.app.headers, params=None, ctrl=LOGIN_CTRL) return json_rsp
def clean_safely(self) -> None: int_curr_time = curr_time() # 过滤删除过于久远的 self._posters = { key: poster for key, poster in self._posters.items() if poster.user_latest_post_time + 12 * 3600 > int_curr_time }
def activate(key_index: str): curr_time = utils.curr_time() # 永久就是 key_expired_time 为 0,否则是有效时间长度 with conn: conn.execute( 'UPDATE keys SET key_created_time = ?, key_expired_time = CASE' ' WHEN key_expired_time!=0 THEN ? + key_expired_time ELSE 0 END' ' WHERE key_index=? and key_created_time=0', (curr_time, curr_time, key_index))
async def app_heartbeat(user): extra_params = { 'access_key': user.dict_bili['access_key'], 'ts': utils.curr_time(), } params = user.sort_and_sign(extra_params) url = f'{API_LIVE}/mobile/userOnlineHeart' payload = {'roomid': 23058, 'scale': 'xhdpi'} json_rsp = await user.bililive_session.request_json('POST', url, data=payload, headers=user.dict_bili['appheaders'], params=params) return json_rsp
async def join(user, raffle_id): extra_params = { 'access_key': user.dict_bili['access_key'], 'ts': utils.curr_time(), 'id': raffle_id, } params = user.sort_and_sign(extra_params) url = f'{API_LIVE}/lottery/v1/Storm/join' json_rsp = await user.bililive_session.request_json('POST', url, headers=user.dict_bili['appheaders'], params=params) return json_rsp
def weight(self) -> int: curr_time = utils.curr_time() weight = 0 if self.latest_guard_time + self.GUARD_DELAY > curr_time: weight += 6 if self.latest_tv_time + self.TV_DELAY > curr_time: weight += 1 if self.latest_storm_time + self.STORM_DELAY > curr_time: weight += 2 return weight
async def sign_group(user, group_id, owner_uid): extra_params = { 'access_key': user.dict_bili["access_key"], 'group_id': group_id, 'owner_id': owner_uid, 'ts': utils.curr_time(), } params = user.sort_and_sign(extra_params) url = f'https://api.vc.bilibili.com/link_setting/v1/link_setting/sign_in' json_rsp = await user.other_session.request_json('GET', url, headers=user.dict_bili['appheaders'], params=params) return json_rsp
async def check(user, dyn_raffle_status: DynRaffleStatus): if not dyn_raffle_sql.is_raffleid_duplicate(dyn_raffle_status.dyn_id): user.info([f'{dyn_raffle_status.doc_id}的动态抽奖通过重复性过滤'], True) dyn_raffle_sql.insert_dynraffle_status_table(dyn_raffle_status) max_sleeptime = max( min(35, dyn_raffle_status.lottery_time - utils.curr_time() - 10), 0) return (1, (0, max_sleeptime), -2, dyn_raffle_status), user.info([f'{dyn_raffle_status.doc_id}的动态抽奖未通过重复性过滤'], True) return None
async def init(): key_path = f'{path.dirname(path.realpath(__file__))}/key' with open(f'{key_path}/admin_privkey.pem', 'rb') as f: admin_privkey = rsa.PrivateKey.load_pkcs1(f.read()) app = web.Application() webserver = WebServer(admin_privkey) app.router.add_get('/', webserver.intro) app.router.add_get('/is_in/{roomid}', webserver.check_index) runner = web.AppRunner(app) await runner.setup() site = web.TCPSite(runner, '0.0.0.0', 9000) await site.start() wanted_time = 0 while True: await webserver.refresh_and_get_rooms() await asyncio.sleep(wanted_time - utils.curr_time() + 3) wanted_time = utils.curr_time() + await webserver.push_roomids() await asyncio.sleep(2)
async def get_info_by_user_app(user): url = f'{API_LIVE}/xlive/app-room/v1/index/getInfoByUser' # {"code": -101, "message": "账号未登录", "ttl": 1} extra_params = { 'access_key': user.dict_bili['access_key'], 'ts': utils.curr_time(), 'room_id': '23058' } params = user.sort_and_sign(extra_params) json_rsp = await user.bililive_session.request_json( 'GET', url, params=params, headers=user.dict_bili['appheaders']) return json_rsp
async def fetch_giftbags(user): json_rsp = await user.req_s(UtilsReq.fetch_giftbags, user) gift_bags = [] cur_time = utils.curr_time() for gift in json_rsp['data']['list']: bag_id = gift['bag_id'] gift_id = gift['gift_id'] gift_num = gift['gift_num'] gift_name = gift['gift_name'] expire_at = gift['expire_at'] left_time = None if not expire_at else expire_at - cur_time gift_bags.append((bag_id, gift_id, gift_num, gift_name, left_time)) return gift_bags