From f6fcd9b1e0d47291f6678e76615357dd6e2d1e99 Mon Sep 17 00:00:00 2001 From: Dawnnnnnn <1050596704@qq.com> Date: Sun, 26 Jul 2020 18:32:41 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9B=86=E6=88=90=E5=B0=8F=E5=BF=83=E5=BF=83?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=8F=8A=E8=87=AA=E5=8A=A8=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E5=8B=8B=E7=AB=A0=E5=8A=9F=E8=83=BD=20fix=20#324=20#309?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 4 ++ OnlineHeart.py | 10 ++- TCP_monitor.py | 3 +- Tasks.py | 46 +++++++++++++ bilibili.py | 102 +++++++++++++++++++++++++---- bilibiliCilent.py | 156 ++++++++++++++++++++++++++------------------- conf/bilibili.conf | 12 ++-- conf/user.conf | 14 ++++ encrypt.py | 66 ------------------- guardLottery.py | 81 ----------------------- run.py | 3 - utils.py | 67 +++++++++++++++++-- 12 files changed, 320 insertions(+), 244 deletions(-) delete mode 100644 encrypt.py delete mode 100644 guardLottery.py diff --git a/Dockerfile b/Dockerfile index 84664ef8..77f38bab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,10 @@ ENV LIBRARY_PATH=/lib:/usr/lib \ WORKDIR /app RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && \ + apk add --no-cache tzdata && \ + cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ + echo "Asia/Shanghai" > /etc/timezone && \ + apk del tzdata && \ apk add --no-cache build-base git && \ git clone https://github.com/Dawnnnnnn/bilibili-live-tools.git /app && \ pip3 install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ && \ diff --git a/OnlineHeart.py b/OnlineHeart.py index 42e2d4e4..f1e7f0b8 100644 --- a/OnlineHeart.py +++ b/OnlineHeart.py @@ -9,8 +9,6 @@ from printer import Printer - - def CurrentTime(): currenttime = int(time.mktime(datetime.datetime.now().timetuple())) return str(currenttime) @@ -39,7 +37,7 @@ async def check_winner(self, i, g, start_time): Statistics().add_to_result(winner["giftTitle"], 1) async def draw_lottery(self): - black_list = ["123", "1111", "测试", "測試", "测一测", "ce-shi", "test", "T-E-S-T", "lala", "我是抽奖标题", "压测", # 已经出现 + black_list = ["123", "1111", "测试", "測試", "测一测", "ce-shi", "test", "T-E-S-T", "lala", "我是抽奖标题", "压测", # 已经出现 "測一測", "TEST", "Test", "t-e-s-t"] # 合理猜想 former_lottery = queue.Queue(maxsize=4) [former_lottery.put(True) for _ in range(4)] @@ -61,7 +59,7 @@ async def draw_lottery(self): for k in black_list: if k in title or k in jp_list: Printer().printer(f"检测到 {i} 号疑似钓鱼类测试抽奖『{title}>>>{jp_list}』" + \ - ",默认不参与,请自行判断抽奖可参与性","Warning","red") + ",默认不参与,请自行判断抽奖可参与性", "Warning", "red") break else: if bilibili().black_status: @@ -81,11 +79,11 @@ async def draw_lottery(self): async def run(self): while 1: try: - Printer().printer("心跳", "Info","green") + Printer().printer("心跳", "Info", "green") response = await self.pcpost_heartbeat() json_response = await response.json(content_type=None) if json_response['code'] in [3, -101]: - Printer().printer(f"cookie过期,将重新登录","Error","red") + Printer().printer(f"cookie过期,将重新登录", "Error", "red") login().login() response1 = await self.apppost_heartbeat() json_response1 = await response1.json(content_type=None) diff --git a/TCP_monitor.py b/TCP_monitor.py index 1a8113be..dad2c452 100644 --- a/TCP_monitor.py +++ b/TCP_monitor.py @@ -11,7 +11,6 @@ from printer import Printer from pkLottery import PKLottery -from guardLottery import GuardLottery from rafflehandler import Rafflehandler @@ -153,7 +152,7 @@ async def parseDanMu(self, dic): elif cmd == 'Storm': pass elif cmd == 'Guard': - await GuardLottery().guard_join(dic["data"]["RoomId"], dic["data"]["Id"]) + pass elif cmd == 'PKLottery': await PKLottery().pk_join(dic["data"]["RoomId"], dic["data"]["Id"]) elif cmd == 'Raffle': diff --git a/Tasks.py b/Tasks.py index 9ab4f31b..b352865b 100644 --- a/Tasks.py +++ b/Tasks.py @@ -6,6 +6,7 @@ import os import configloader import utils +import ast from printer import Printer @@ -85,6 +86,8 @@ async def auto_send_gift(self): # id = json_res['data'][j]['id'] # temp_dic[id] = price temp_dic = {1: 100, 6: 1000} + if self.dic_user['send_exheart']['on/off'] == "1": + temp_dic = {1: 100, 6: 1000, 30607: 5000} x, temp = await utils.fetch_bag_list(printer=False) roomid = a[0] today_feed = a[1] @@ -130,11 +133,54 @@ async def sliver2coin(self): json_response1 = await response1.json() Printer().printer(f"银瓜子兑换硬币状态:{json_response1['msg']}", "Info", "green") + async def refresh_medals(self): + if self.dic_user['refresh_medals']['on/off'] == '1': + await utils.refresh_all_gray_medals() + + async def refresh_medals_by_roomid(self): + if self.dic_user['refresh_medals_by_roomid']['on/off'] == "1": + roomids = ast.literal_eval(self.dic_user['refresh_medals_by_roomid']['room_ids']) + await utils.refresh_medals_by_roomids(roomids) + + async def get_rooms(self): + room_ids = [] + response = await bilibili().request_fetchmedal() + json_response = await response.json(content_type=None) + for i in range(0, len(json_response['data']['fansMedalList'])): + short_room_id = json_response['data']['fansMedalList'][i]['roomid'] + response1 = await bilibili().get_room_info(short_room_id) + json_response1 = await response1.json(content_type=None) + long_room_id = json_response1['data']['room_info']['room_id'] + room_ids.append(long_room_id) + return room_ids + + async def XE_heartbeat(self, room_ids, room_id): + index_num = round(24 / len(room_ids)) + data = await bilibili().heart_beat_e(room_id) + for index in range(1, index_num + 1): + try: + # print(f"房间{room_id}休眠{data['heartbeat_interval']}s后开始第 {index} 次") + await asyncio.sleep(data['heartbeat_interval']) + response = await bilibili().heart_beat_x(index, data, room_id) + response = await response.json(content_type=None) + data['ets'] = response['data']['timestamp'] + data['secret_key'] = response['data']['secret_key'] + data['heartbeat_interval'] = response['data']['heartbeat_interval'] + except: + pass + async def run(self): while 1: try: Printer().printer(f"开始执行每日任务", "Info", "green") await self.DoSign() + room_ids = await self.get_rooms() + coroutine_list = [] + for room_id in room_ids: + coroutine_list.append(self.XE_heartbeat(room_ids, room_id)) + await asyncio.wait(coroutine_list) + await self.refresh_medals_by_roomid() + await self.refresh_medals() await self.Daily_bag() await self.Daily_Task() await self.link_sign() diff --git a/bilibili.py b/bilibili.py index adf98fac..f29c3af7 100644 --- a/bilibili.py +++ b/bilibili.py @@ -8,6 +8,7 @@ import requests import rsa import base64 +import uuid from urllib import parse from printer import Printer import aiohttp @@ -241,7 +242,7 @@ def request_load_img(self, url): return requests.get(url) async def request_fetchmedal(self): - url = 'https://api.live.bilibili.com/i/api/medal?page=1&pageSize=50' + url = 'https://api.live.bilibili.com/i/api/medal?page=1&pageSize=168' response = await self.bili_section_get(url, headers=self.dic_bilibili['pcheaders']) return response @@ -432,17 +433,9 @@ async def heart_gift(self): response = await self.bili_section_get(url, headers=self.dic_bilibili['pcheaders']) return response - async def guard_list(self): - url = "http://118.25.108.153:8080/guard" - headers = { - "User-Agent": "bilibili-live-tools/" + str(self.dic_bilibili['uid']) - } - response = requests.get(url, headers=headers, timeout=3) - return response - - async def guard_list_v2(self): - url = "https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=465671" - response = requests.get(url, headers=self.dic_bilibili['pcheaders'], timeout=3) + async def get_room_info(self, roomid): + url = f"https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id={roomid}" + response = await self.bili_section_get(url, headers=self.dic_bilibili['pcheaders'], timeout=3) return response async def pk_list(self): @@ -568,3 +561,88 @@ async def req_area_list(self): url = "http://api.live.bilibili.com/room/v1/Area/getList" response = await self.bili_section_get(url) return response + + async def heart_beat_e(self, room_id): + response = await self.get_room_info(room_id) + json_response = await response.json(content_type=None) + parent_area_id = json_response['data']['room_info']['parent_area_id'] + area_id = json_response['data']['room_info']['area_id'] + + url = 'https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/E' + headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://live.bilibili.com', + 'Referer': f'https://live.bilibili.com/{room_id}', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + 'Cookie': self.dic_bilibili['cookie'], + } + payload = { + 'id': [parent_area_id, area_id, 0, room_id], + 'device': f'["{self.calc_sign(str(uuid.uuid4()))}","{uuid.uuid4()}"]', + 'ts': int(time.time()) * 1000, + 'is_patch': 0, + 'heart_beat': [], + 'ua': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36', + 'csrf_token': self.dic_bilibili['csrf'], + 'csrf': self.dic_bilibili['csrf'], + 'visit_id': '' + } + data = parse.urlencode(payload) + # {"code":0,"message":"0","ttl":1,"data":{"timestamp":1595342828,"heartbeat_interval":300,"secret_key":"seacasdgyijfhofiuxoannn","secret_rule":[2,5,1,4],"patch_status":2}} + response = await self.bili_section_post(url, headers=headers, data=data) + response = await response.json(content_type=None) + payload['ets'] = response['data']['timestamp'] + payload['secret_key'] = response['data']['secret_key'] + payload['heartbeat_interval'] = response['data']['heartbeat_interval'] + payload['secret_rule'] = response['data']['secret_rule'] + return payload + + async def heart_beat_x(self, index, payload, room_id): + response = await self.get_room_info(room_id) + json_response = await response.json(content_type=None) + parent_area_id = json_response['data']['room_info']['parent_area_id'] + area_id = json_response['data']['room_info']['area_id'] + url = 'https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/X' + headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://live.bilibili.com', + 'Referer': f'https://live.bilibili.com/{room_id}', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + 'Cookie': self.dic_bilibili['cookie'], + } + s_data = { + "t": { + 'id': [parent_area_id, area_id, index, room_id], + "device": payload['device'], # LIVE_BUVID + "ets": payload['ets'], + "benchmark": payload['secret_key'], + "time": payload['heartbeat_interval'], + "ts": int(time.time()) * 1000, + "ua": payload['ua'] + }, + "r": payload['secret_rule'] + } + t = s_data['t'] + payload = { + 's': self.generate_s(s_data), + 'id': t['id'], + 'device': t['device'], + 'ets': t['ets'], + 'benchmark': t['benchmark'], + 'time': t['time'], + 'ts': t['ts'], + "ua": t['ua'], + 'csrf_token': self.dic_bilibili['csrf'], + 'csrf': self.dic_bilibili['csrf'], + 'visit_id': '', + } + payload = parse.urlencode(payload) + # {"code":0,"message":"0","ttl":1,"data":{"heartbeat_interval":300,"timestamp":1595346846,"secret_rule":[2,5,1,4],"secret_key":"seacasdgyijfhofiuxoannn"}} + response = await self.bili_section_post(url, headers=headers, data=payload) + return response + + # 加密s + def generate_s(self, data): + url = 'http://127.0.0.1:3000/enc' + response = requests.post(url, json=data).json() + return response['s'] diff --git a/bilibiliCilent.py b/bilibiliCilent.py index e304641a..a7d38b73 100644 --- a/bilibiliCilent.py +++ b/bilibiliCilent.py @@ -8,6 +8,7 @@ import asyncio import random import struct +import zlib import json import sys @@ -71,9 +72,10 @@ class bilibiliClient(): def __init__(self, roomid, area): self.bilibili = bilibili() + self._protocol_version = self.bilibili.dic_bilibili['_protocolversion'] self._reader = None self._writer = None - self._uid = None + self._uid = int(100000000000000 + 200000000000000 * random.random()) self.connected = False self._UserCount = 0 self.dic_bulletin = { @@ -91,15 +93,13 @@ def close_connection(self): async def connectServer(self): try: - reader, writer = await asyncio.open_connection(self.bilibili.dic_bilibili['_ChatHost'], - self.bilibili.dic_bilibili['_ChatPort']) + self._reader, self._writer = await asyncio.open_connection(self.bilibili.dic_bilibili['_ChatHost'], + self.bilibili.dic_bilibili['_ChatPort']) except: print("连接无法建立,请检查本地网络状况") await asyncio.sleep(5) return - self._reader = reader - self._writer = writer - if (await self.SendJoinChannel(self._roomId) == True): + if await self.SendJoinChannel(): self.connected = True Printer().printer(f'[{self.area}分区] 连接 {self._roomId} 弹幕服务器成功', "Info", "green") await self.ReceiveMessageLoop() @@ -109,33 +109,45 @@ async def HeartbeatLoop(self): await asyncio.sleep(0.5) while self.connected: - await self.SendSocketData(0, 16, self.bilibili.dic_bilibili['_protocolversion'], 2, 1, "") + await self.SendSocketData(ver=self._protocol_version, action=2, body="") await asyncio.sleep(30) - async def SendJoinChannel(self, channelId): - self._uid = (int)(100000000000000.0 + 200000000000000.0 * random.random()) - body = '{"roomid":%s,"uid":%s}' % (channelId, self._uid) - await self.SendSocketData(0, 16, self.bilibili.dic_bilibili['_protocolversion'], 7, 1, body) - return True + async def SendJoinChannel(self): + body = json.dumps({ + "roomid": self._roomId, + "uid": self._uid, + # "protover": 2, + # "key": token, + }, separators=(',', ':')) + return await self.SendSocketData(ver=self._protocol_version, action=7, body=body) - async def SendSocketData(self, packetlength, magic, ver, action, param, body): + async def SendSocketData(self, ver, action, body): bytearr = body.encode('utf-8') - if packetlength == 0: - packetlength = len(bytearr) + 16 - sendbytes = struct.pack('!IHHII', packetlength, magic, ver, action, param) - if len(bytearr) != 0: - sendbytes = sendbytes + bytearr + header_len = 16 + body_len = len(bytearr) + packet_len = 16 + body_len + sequence = 1 + sendbytes = struct.pack(f'!IHHII{body_len}s', + packet_len, header_len, ver, action, sequence, bytearr) try: self._writer.write(sendbytes) - except: - Printer().printer(f"Error when self._writer.write(sendbytes): {sys.exc_info()[0]}, {sys.exc_info()[1]}","Error","red") + except Exception: + Printer().printer(f"Error when self._writer.write(sendbytes): {sys.exc_info()[0]}, {sys.exc_info()[1]}", + "Error", "red") self.connected = False + return False try: await self._writer.drain() - except ConnectionError: - pass + except (ConnectionResetError, ConnectionAbortedError) as e: + # [WinError 10054] 远程主机强迫关闭了一个现有的连接。 + # [WinError 10053] 你的主机中的软件中止了一个已建立的连接。 + Printer().printer(f"Failed @ self._writer.drain(): {repr(e)}", "Error", "red") + return False except Exception: - Printer().printer(f"Error when self._writer.drain(): {sys.exc_info()[0]}, {sys.exc_info()[1]}","Error","red") + Printer().printer(f"Error when self._writer.drain(): {sys.exc_info()[0]}, {sys.exc_info()[1]}", + "Error", "red") + return False + return True async def ReadSocketData(self, len_wanted): bytes_data = b'' @@ -175,65 +187,81 @@ async def ReadSocketData(self, len_wanted): self.close_connection() return None - if not tmp: + if not len(tmp): Printer().printer(f"主动关闭或者远端主动发来FIN @[{self.area}分区]{self._roomId}","Error","red") self.close_connection() await asyncio.sleep(1) return None else: - bytes_data = bytes_data + tmp - len_remain = len_remain - len(tmp) + bytes_data += tmp + len_remain -= len(tmp) return bytes_data async def ReceiveMessageLoop(self): - while self.connected == True: - tmp = await self.ReadSocketData(16) - if tmp is None: + while self.connected: + length = await self.ReadSocketData(4) + if length is None: break - expr, = struct.unpack('!I', tmp[:4]) + packet_len, = struct.unpack('!I', length) + body = await self.ReadSocketData(packet_len-4) + if body is None: + break - num, = struct.unpack('!I', tmp[8:12]) + await self.parse_packet(packet_len, body) - num2 = expr - 16 + async def parse_packet(self, packet_len: int, body: bytes): + """ + len(body) == packet_len - 4 + :param packet_len: length of whole packet + :param body: header except packet_len + subsequent main body + """ + # 基础假设是每个packet都有16字节header的保守序列,没有另外再先读取header_len然后读header + header_len, ver, action, sequence = struct.unpack('!HHII', body[:12]) + body = body[12:] + # print(packet_len, header_len, ver, action, sequence, body) - tmp = await self.ReadSocketData(num2) - if tmp is None: - break + if action == 3: + # 3 人气值,数据不是JSON,是4字节整数 + self._UserCount, = struct.unpack('!I', body) + else: + try: + dic = json.loads(body) + except UnicodeDecodeError: + inner_packet = zlib.decompress(body) + # print(f'{packet_len} 字节解压出 {inner_packet.count(b"cmd")} 条消息') - if num2 != 0: - num -= 1 - if num == 0 or num == 1 or num == 2: - num3, = struct.unpack('!I', tmp) - self._UserCount = num3 - continue - elif num == 3 or num == 4: - try: - messages = tmp.decode('utf-8') - except: - continue - try: - await self.parseDanMu(messages) - except Exception: - Printer().printer(f'Failed when parsing: {messages}\n{traceback.format_exc()}', "Error", "red") - continue - elif num == 5 or num == 6 or num == 7: - continue - else: - if num != 16: - pass - else: - continue + pack_p = 0 + packs_len = len(inner_packet) + while pack_p < packs_len: + pack_len, = struct.unpack('!I', inner_packet[pack_p:pack_p+4]) + await self.parse_packet(pack_len, inner_packet[pack_p+4:pack_p+pack_len]) + pack_p += pack_len + return + except json.JSONDecodeError as e: + Printer().printer(f"{repr(e)} when json decode: {body}", "Error", "red") + return + except Exception: + Printer().printer(f"Failed when parse_packet: {body}\n{traceback.format_exc()}", "Error", "red") + return - async def parseDanMu(self, messages): - try: - dic = json.loads(messages) - except: - return + if action == 5: + try: + await self.parseDanMu(dic) + except Exception: + Printer().printer(f"Failed when parsing: {dic}\n{traceback.format_exc()}", "Error", "red") + elif action == 8: + # 26, 16, 2, 8, 1, b'{"code":0}' + pass + else: + # lyyyuna原版有action=17就不去请求body的逻辑 + Printer().printer(f"异常action值: {packet_len, header_len, ver, action, sequence, dic}", "Warning", "red") + async def parseDanMu(self, dic): cmd = dic.get('cmd') if cmd is None: + Printer().printer(f"No cmd: {dic}", "Warning", "red") return if cmd == 'LIVE': @@ -329,4 +357,4 @@ async def parseDanMu(self, messages): pass else: # Printer().printer(f"出现一个未知msg @[{self.area}分区]{self._roomId} {dic}", "Warning", "red") - pass + pass \ No newline at end of file diff --git a/conf/bilibili.conf b/conf/bilibili.conf index d82e97b5..961a0de0 100644 --- a/conf/bilibili.conf +++ b/conf/bilibili.conf @@ -8,7 +8,7 @@ platform = android app_secret = 560c52ccd288fed045859ed18bffd973 _CIDInfoUrl = http://live.bilibili.com/api/player?id=cid: _ChatPort = 2243 -_protocolversion = 1 +_protocolversion = 2 _ChatHost = livecmt-2.bilibili.com activity_name = access_key = @@ -40,11 +40,11 @@ username = password = [saved-session] -access_key = -cookie = -csrf = -uid = -refresh_token = +access_key = +cookie = +csrf = +uid = +refresh_token = [types] int = _ChatPort _protocolversion diff --git a/conf/user.conf b/conf/user.conf index def0296e..46272f3e 100644 --- a/conf/user.conf +++ b/conf/user.conf @@ -25,6 +25,20 @@ on/off = 1 on/off = 0 schedule = +# 刷新所有灰色勋章 +[refresh_medals] +on/off = 0 + +# 根据房间号刷新灰色勋章(同时支持长短位房间号) +[refresh_medals_by_roomid] +on/off = 0 +room_ids = [3,6] + +# 自动送礼时把小心心也当作能送的礼物(优先刷新灰色勋章,剩余的才会送) +[send_exheart] +on/off = 0 + + # 监控服务器 [monitoy_server] on/off = 1 diff --git a/encrypt.py b/encrypt.py deleted file mode 100644 index b59445f3..00000000 --- a/encrypt.py +++ /dev/null @@ -1,66 +0,0 @@ -import io -from six import int2byte - -dict_b = { - 5376: -1, 13312: 0, 13568: 1, 13824: 2, 14080: 3, 14336: 4, 14592: 5, - 14848: 6, 15104: 7, 15360: 8, 15616: 9, 15872: 10, 16128: 11, 16384: 12, - 16640: 13, 16896: 14, 17152: 15, 17408: 16, 17664: 17, 17920: 18, 18176: - 19, 18432: 20, 18688: 21, 18944: 22, 19200: 23, 19456: 24, 19968: 25, - 20224: 26, 20480: 27, 20736: 28, 20992: 29, 21248: 30, 21504: 31, 21760: - 32, 22016: 33, 22272: 34, 22528: 35, 22784: 36, 23040: 37, 23296: 38, - 23552: 39, 23808: 40, 24064: 41, 24320: 42, 24576: 43, 24832: 44, 25088: - 45, 25344: 46, 25600: 47, 25856: 48, 26112: 49, 26368: 50, 26624: 51, - 26880: 52, 27136: 53, 27392: 54, 27648: 55, 27904: 56, 28160: 57, 28416: - 58, 28672: 59, 28928: 60, 29184: 61, 29440: 62, 29696: 63, 29952: 64, - 30208: 65, 30464: 66, 30720: 67, 30976: 68, 31232: 69, 31488: 70, 31744: - 71, 32000: 72, 32256: 73, 32512: 74, 32768: 75, 33024: 76, 33280: 77, - 33536: 78, 33792: 79, 34048: 80, 34304: 81, 34560: 82, 34816: 83, 35072: - 84, 35328: 85, 35584: 86, 35840: 87, 36096: 88, 36352: 89, 36608: 90, - 36864: 91, 37120: 92, 37376: 93, 37632: 94, 37888: 95, 38144: 96, 38400: - 97, 38656: 98, 38912: 99, 39168: 100, 39424: 101, 39680: 102, 39936: 103, - 40192: 104, 40448: 105, 41216: 106, 41472: 107, 41728: 108, 42240: 109, - 67072: 110, 73728: 111, 73984: 112, 74240: 113, 77824: 114, 78080: 115, - 78336: 116, 78592: 117, 82944: 118, 83200: 119, 92160: 120, 92416: 121, - 131072: 122, 131328: 123, 131584: 124, 131840: 125, 132096: 126, 132352: - 127, 132608: 128, 132864: 129, 133120: 130, 133376: 131, 133632: 132, - 133888: 133, 134144: 134, 134400: 135, 134656: 136, 134912: 137, 135168: - 138, 135424: 139, 135680: 140, 135936: 141, 136192: 142, 136448: 143, - 136704: 144, 136960: 145, 137216: 146, 137472: 147, 137728: 148, 137984: - 149, 138240: 150, 138496: 151, 138752: 152, 139008: 153, 139264: 154, - 139520: 155, 139776: 156, 140032: 157, 140288: 158, 140544: 159, 140800: - 160, 141056: 161, 141312: 162, 141568: 163, 141824: 164, 142080: 165, - 142336: 166, 142592: 167, 142848: 168, 143104: 169, 143360: 170, 143616: - 171, 143872: 172, 144128: 173, 144384: 174, 144640: 175, 144896: 176, - 145152: 177, 145408: 178, 145664: 179, 145920: 180, 146176: 181, 146432: - 182, 146688: 183, 146944: 184, 147200: 185, 147456: 186, 147712: 187, - 147968: 188, 148224: 189, 148480: 190, 148736: 191, 148992: 192, 149248: - 193, 149504: 194, 149760: 195, 150016: 196, 150272: 197, 150528: 198, - 150784: 199, 151040: 200, 151296: 201, 151552: 202, 151808: 203, 152064: - 204, 152320: 205, 152576: 206, 152832: 207, 153088: 208, 153344: 209, - 153600: 210, 153856: 211, 154112: 212, 154368: 213, 154624: 214, 154880: - 215, 155136: 216, 155392: 217, 155648: 218, 155904: 219, 156160: 220, - 156416: 221, 156672: 222, 156928: 223, 157184: 224, 157440: 225, 157696: - 226, 157952: 227, 158208: 228, 158464: 229, 158720: 230, 158976: 231, - 159232: 232, 159488: 233, 159744: 234, 160000: 235, 160256: 236, 160512: - 237, 160768: 238, 161024: 239, 161280: 240, 161536: 241, 161792: 242, - 162048: 243, 162304: 244, 162560: 245, 162816: 246, 163072: 247, 163328: - 248, 163584: 249, 163840: 250, 164096: 251, 164352: 252, 164608: 253, - 164864: 254, 165120: 255} - - -def decrypt(strings): - stream = io.BytesIO() - done = False - for ch in strings: - b1 = ord(ch) & ((1 << 8) - 1) - try: - b2 = dict_b[ord(ch) - b1] - except KeyError: - raise ValueError('Error') - b = int2byte(b1) if b2 == -1 else int2byte(b1) + int2byte(b2) - if len(b) == 1: - if done: - raise ValueError('Error') - done = True - stream.write(b) - return stream.getvalue() diff --git a/guardLottery.py b/guardLottery.py deleted file mode 100644 index c403d79f..00000000 --- a/guardLottery.py +++ /dev/null @@ -1,81 +0,0 @@ -import traceback -import asyncio - -from bilibili import bilibili -from schedule import Schedule -from printer import Printer -import utils -import encrypt -import json -import brotli - - -class GuardLottery: - last_guard_room = 0 - had_gotted_guard = [] - - async def guard_lottery(self): - for k in range(1): - try: - response = await bilibili().guard_list() - json_response = response.json() - break - except Exception: - continue - else: - Printer().printer("连接舰长服务器失败,尝试从CDN拉取数据", "Error", "red") - response = await bilibili().guard_list_v2() - encrypt_content = response.json()['data']['room_info']['description'].replace('b6','').replace('
','').replace('','') - json_response = json.loads(brotli.decompress(encrypt.decrypt(encrypt_content)).decode()) - for i in range(0, len(json_response)): - GuardId = json_response[i]['Id'] - if GuardId not in GuardLottery.had_gotted_guard and GuardId != 0: - GuardLottery.had_gotted_guard.append(GuardId) - OriginRoomId = json_response[i]['RoomId'] - await self.guard_join(OriginRoomId, GuardId) - await asyncio.sleep(0.2) - - async def guard_join(self, OriginRoomId, GuardId): - if Schedule().scheduled_sleep: - Printer().printer(f"定时休眠,跳过房间 {OriginRoomId} 编号 {GuardId} 的上船奖励", "Info", "green") - return - if bilibili().black_status: - Printer().printer(f"黑屋休眠,跳过房间 {OriginRoomId} 编号 {GuardId} 的上船奖励", "Info", "green") - return - if not OriginRoomId == GuardLottery.last_guard_room: - result = await utils.check_room_true(OriginRoomId) - if True in result: - Printer().printer(f"检测到房间 {OriginRoomId} 的钓鱼操作", "Warning", "red") - return - await bilibili().post_watching_history(OriginRoomId) - GuardLottery.last_guard_room = OriginRoomId - # response2 = await bilibili().get_gift_of_captain_v2(OriginRoomId, GuardId) - # json_response2 = await response2.json(content_type=None) - # print(json_response2) - response2 = await bilibili().get_gift_of_captain(OriginRoomId, GuardId) - json_response2 = await response2.json(content_type=None) - if json_response2['code'] == 0: - Printer().printer(f"获取到房间 {OriginRoomId} 编号 {GuardId} 的上船奖励: " - f"{json_response2['data']['award_text']}" if json_response2['data']['award_text'] else - f"获取到房间 {OriginRoomId} 编号 {GuardId} 的上船奖励: " - f"{json_response2['data']['award_name']}X{json_response2['data']['award_num']}", - "Lottery", "cyan") - elif json_response2['code'] == -403 and json_response2['msg'] == "访问被拒绝": - Printer().printer(f"获取房间 {OriginRoomId} 编号 {GuardId} 的上船奖励: {json_response2['message']}", - "Lottery", "cyan") - print(json_response2) - elif json_response2['code'] == 400 and json_response2['msg'] == "你已经领取过啦": - Printer().printer(f"房间 {OriginRoomId} 编号 {GuardId} 的上船奖励已领过", - "Info", "green") - else: - Printer().printer(f"房间 {OriginRoomId} 编号 {GuardId} 的上船奖励领取出错: {json_response2}", - "Error", "red") - - async def run(self): - while True: - try: - await self.guard_lottery() - await asyncio.sleep(300) - except Exception: - await asyncio.sleep(30) - Printer().printer(traceback.format_exc(), "Error", "red") diff --git a/run.py b/run.py index 4f5ac320..31ea4aa0 100644 --- a/run.py +++ b/run.py @@ -13,7 +13,6 @@ import threading import biliconsole from pkLottery import PKLottery -from guardLottery import GuardLottery from schedule import Schedule import configloader import os @@ -36,7 +35,6 @@ task3 = LotteryResult() task4 = connect() task5 = PKLottery() -task6 = GuardLottery() tasks1 = [ login().login_new() @@ -57,7 +55,6 @@ task3.query(), rafflehandler.run(), task5.run(), - task6.run() ] diff --git a/utils.py b/utils.py index 8655af86..b5c4c99e 100644 --- a/utils.py +++ b/utils.py @@ -38,7 +38,7 @@ def seconds_until_tomorrow(): async def fetch_medal(printer=True): if printer: - Printer().printer('查询勋章信息',"Info","green") + Printer().printer('查询勋章信息', "Info", "green") print( '{} {} {:^12} {:^10} {} {:^6} '.format(adjust_for_chinese('勋章'), adjust_for_chinese('主播昵称'), '亲密度', '今日的亲密度', @@ -60,7 +60,7 @@ async def fetch_medal(printer=True): if json_response['code'] == 0: for i in json_response['data']['fansMedalList']: if i['status'] == 1: - roomid = i.get('roomid', 0) # 主站获取的勋章没有直播间 + roomid = i.get('roomid', 0) # 主站获取的勋章没有直播间 today_feed = i['today_feed'] day_limit = i['day_limit'] if printer: @@ -224,9 +224,11 @@ async def send_gift_web(roomid, giftid, giftnum, bagid): response1 = await bilibili().request_send_gift_web(giftid, giftnum, bagid, ruid, biz_id) json_response1 = await response1.json() if json_response1['code'] == 0: - Printer().printer(f"送出礼物{json_response1['data']['gift_name']}x{json_response1['data']['gift_num']}","Info","green") + Printer().printer(f"送出礼物{json_response1['data']['gift_name']}x{json_response1['data']['gift_num']}到{roomid}房间", + "Info", + "green") else: - Printer().printer(f"错误:{json_response1['msg']}","Error","red") + Printer().printer(f"错误:{json_response1['msg']}", "Error", "red") async def check_room_true(roomid): @@ -272,3 +274,60 @@ async def reconnect(area=None): async def check_area_list(area_list, **kwargs): for area_id in area_list: await connect().check_area(area_id, **kwargs) + + +async def fetch_gray_medals(): + gray_medals = [] + response = await bilibili().request_fetchmedal() + json_response = await response.json(content_type=None) + for i in range(0, len(json_response['data']['fansMedalList'])): + if json_response['data']['fansMedalList'][i]['is_lighted'] == 0: + gray_medal = {} + gray_medal['medal_name'] = json_response['data']['fansMedalList'][i]['medal_name'] + gray_medal['roomid'] = json_response['data']['fansMedalList'][i]['roomid'] + gray_medals.append(gray_medal) + return gray_medals + + +async def get_all_of_my_hearts(): + hearts = [] + response = await bilibili().request_fetch_bag_list() + json_response = await response.json(content_type=None) + for i in range(len(json_response['data']['list'])): + gift_name = json_response['data']['list'][i]['gift_name'] + gift_id = (json_response['data']['list'][i]['gift_id']) + if gift_name == "小心心" or gift_id == 30607: + expireat = json_response['data']['list'][i]['expire_at'] + bag_id = json_response['data']['list'][i]['bag_id'] + gift_num = json_response['data']['list'][i]['gift_num'] + for _ in range(gift_num): + hearts.append([bag_id, 1, expireat]) + + return hearts + + +async def refresh_all_gray_medals(): + gray_medals = await fetch_gray_medals() + hearts = await get_all_of_my_hearts() + if hearts: + for gray_medal in gray_medals: + if len(hearts) > 0: + heart = hearts.pop() + await send_gift_web(gray_medal['roomid'], 30607, 1, heart[0]) + else: + pass + else: + pass + + +async def refresh_medals_by_roomids(roomids): + hearts = await get_all_of_my_hearts() + if hearts: + for roomid in roomids: + if len(hearts) > 0: + heart = hearts.pop() + await send_gift_web(roomid, 30607, 1, heart[0]) + else: + pass + else: + pass