Repository: yjqiang/bilibili-live-tools Branch: master Commit: cacd9dba37bd Files: 26 Total size: 131.5 KB Directory structure: gitextract_441lrr1s/ ├── .gitignore ├── Dockerfile ├── LICENSE ├── OnlineHeart.py ├── README.md ├── Silver.py ├── Tasks.py ├── bili_console.py ├── bilibili.py ├── bilitimer.py ├── conf/ │ ├── bilibili.toml │ ├── color.toml │ ├── title.toml │ ├── title_init.py │ └── user.toml ├── configloader.py ├── connect.py ├── danmu.py ├── online_net.py ├── printer.py ├── rafflehandler.py ├── requirements.txt ├── run.py ├── statistics.py ├── ugly_auto_reboot.py └── utils.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ .DS_Store *.iml *.xml ================================================ FILE: Dockerfile ================================================ FROM python:3.6-alpine ENV LIBRARY_PATH=/lib:/usr/lib \ USER_NAME='' \ USER_PASSWORD='' WORKDIR /app RUN echo https://mirrors.tuna.tsinghua.edu.cn/alpine/v3.8/main > /etc/apk/repositories; \ echo https://mirrors.tuna.tsinghua.edu.cn/alpine/v3.8/community >> /etc/apk/repositories RUN apk add --no-cache libpng freetype libstdc++ libjpeg-turbo RUN apk add --no-cache --virtual .build-deps \ python-dev \ py-pip \ jpeg-dev \ zlib-dev \ \ gcc \ build-base \ libpng-dev \ musl-dev \ freetype-dev RUN ln -s /usr/include/locale.h /usr/include/xlocale.h RUN apk add --no-cache git && \ git clone https://github.com/yjqiang/bilibili-live-tools /app && \ pip install --no-cache-dir -r requirements.txt && \ rm -r /var/cache/apk && \ rm -r /usr/share/man && \ apk del .build-deps ENTRYPOINT git pull && \ pip install --no-cache-dir -r requirements.txt && \ sed -i ''"$(cat conf/bilibili.toml -n | grep "username = \"\"" | awk '{print $1}')"'c '"$(echo "username = \"${USER_NAME}\"")"'' conf/bilibili.toml && \ sed -i ''"$(cat conf/bilibili.toml -n | grep "password = \"\"" | awk '{print $1}')"'c '"$(echo "password = \"${USER_PASSWORD}\"")"'' conf/bilibili.toml && \ python ./run.py ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2018 Dawnspace Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: OnlineHeart.py ================================================ from online_net import OnlineNet import time import asyncio import printer def CurrentTime(): currenttime = int(time.time()) return currenttime async def heartbeat(): printer.info(["心跳"], True) json_response = await OnlineNet().req('apppost_heartbeat') json_response = await OnlineNet().req('pcpost_heartbeat') json_response = await OnlineNet().req('heart_gift') # print('pcpost_heartbeat', json_response) # 因为休眠时间差不多,所以放到这里,此为实验性功能 async def draw_lottery(): blacklist = ['test', 'TEST', '测试', '加密'] max = 10000 min = 50 while max > min: # print(min, max) middle = int((min + max + 1) / 2) code_middle = (await OnlineNet().req('get_lotterylist', middle))["code"] if code_middle: code_middle1 = (await OnlineNet().req('get_lotterylist', middle + 1))['code'] code_middle2 = (await OnlineNet().req('get_lotterylist', middle + 2))['code'] if code_middle1 and code_middle2: max = middle - 1 else: min = middle + 1 else: min = middle print('最新实物抽奖id为', min, max) for i in range(max - 30, max + 1): json_response = await OnlineNet().req('get_lotterylist', i) print('id对应code数值为', json_response['code'], i) # -400 不存在 if not json_response['code']: temp = json_response['data']['title'] if any(word in temp for word in blacklist): print("检测到疑似钓鱼类测试抽奖,默认不参与,请自行判断抽奖可参与性") # print(temp) else: check = json_response['data']['typeB'] for g, value in enumerate(check): join_end_time = value['join_end_time'] join_start_time = value['join_start_time'] ts = CurrentTime() if int(join_end_time) > int(ts) > int(join_start_time): json_response1 = await OnlineNet().req('get_gift_of_lottery', i, g) printer.info([f'参与实物抽奖回显:{json_response1}'], True) async def run(): while 1: # login.HandleExpire() await heartbeat() # await draw_lottery() await asyncio.sleep(300) ================================================ FILE: README.md ================================================ # bilibili-live-tools :no_entry: [DEPRECATED] ~~单用户比利脚本~~ ***1.本项目作为老项目已经被新项目取代 https://github.com/yjqiang/bili2.0*** 2.新项目初期只是想作为多用户分支,结果做完后发现,比老项目做了很多。比如结构优化、很多函数调整、web_session 独立以及一些新的功能等,而且对单用户也很友好 3.旧项目不再提供任何代码上的修改等,***完全废除***。但是这里面的已存在的 issue 仍然继续追踪 yjqiang分支是一个次分支,再次感谢主分支所有参与者的基础奠定 ## Docker使用介绍 - 直接拉取构建好的Docker镜像 ``` docker run -d -e USER_NAME=B站登陆账户 -e USER_PASSWORD=登陆密码 --name 容器名字(随意) zuosc/bilibili-live-tools-python ``` eg: docker run -d -e USER_NAME=xxxxxxxxxxx -e USER_PASSWORD=pwd --name bilibili zuosc/bilibili-live-tools-python - 本地构建Docker镜像 1、构建镜像 ``` docker build -t image名称 . ``` eg: docker build -t bilibili_img . 2、运行镜像 ``` docker run -d -e USER_NAME=B站登陆账户 -e USER_PASSWORD=登陆密码 --name 容器名字(随意) image名称 ``` eg: docker run -d -e USER_NAME=xxxxxxxxxxx -e USER_PASSWORD=pwd --name bilibili bilibili_img ## 其他版本Docker使用介绍 docker使用 https://github.com/Muromi-Rikka/bilibili-live-tools-docker docker使用 https://github.com/zsnmwy/bilibili-live-tools-docker pythonista3(ios) https://www.jianshu.com/p/669e63b5ec2b 依赖包 https://github.com/yjqiang/bilibili-live-tools/blob/master/requirements.txt 运行方法 run.py 多用户版本 https://github.com/yjqiang/bili2.0 二次开发 https://github.com/Hsury/Bilibili-Toolkit 目前已完成: ------ 每日签到 双端心跳领取经验 领取银瓜子宝箱 提交每日任务 漫天花雨双端抽奖 小电视PC端抽奖 领取每日包裹奖励 应援团签到 获取心跳礼物 20倍节奏风暴领取 获取总督开通奖励 实物抽奖 清空当日到期礼物 根据亲密度赠送礼物 银瓜子硬币双向兑换 云端验证码识别 主站每日任务(4个) version 1.0.0 ------ 基本稳定 version 1.1.0 ------ 抽奖繁忙重试机制建立(目前只支持了tv,因为只有这一个code) 开始使用f string代替字符串加法或者format,f string大法好 修复b站sb的屏蔽”御姐”用户名关键词这种(倒着切查,其实应该分词查看) 结构方面的调整,一些不必要的对象创建被删除 简单调整代码style 其他细节的改变 version 2.0 ------ 摩天大楼多房间 主站功能(投币分享等)支持 websocket弹幕 总督领取 token refresh and save cookie Queue队列 其他细节的改变 version 2.1 ------ 更新api v4小电视更新 支持风纪委员会 其他修改 version 2.2 ------ 更新wiki 调整bilitimer,改善漏抽问题 弹幕重连机制修复 实物抽奖机制优化 version 3.0 ------ 庆祝多用户发布 风纪委基本100%成功率 环境: ------ python3.6+ 感谢:https://github.com/lyyyuna 感谢:https://github.com/lkeme/BiliHelper 感谢:https://github.com/czp3009/bilibili-api 感谢:https://github.com/lzghzr/bilive_client 本项目采用MIT开源协议 ================================================ FILE: Silver.py ================================================ from online_net import OnlineNet import utils import printer import asyncio # 领取银瓜子 async def GetAward(): temp = await OnlineNet().req('get_time_about_silver') # print (temp['code']) #宝箱领完返回的code为-10017 if temp['code'] == -10017: printer.info(["# 今日宝箱领取完毕"]) else: time_start = temp['data']['time_start'] time_end = temp['data']['time_end'] json_response = await OnlineNet().req('get_silver', time_start, time_end) return json_response async def GetAward_black(): temp = await OnlineNet().req('get_time_about_silver') # print (temp['code']) #宝箱领完返回的code为-10017 if temp['code'] == -10017: printer.info(["# 今日宝箱领取完毕"]) else: time_start = temp['data']['time_start'] time_end = temp['data']['time_end'] for i in range(50): json_response = await OnlineNet().req('get_silver', time_start, time_end) if json_response['code'] != 400: print('宝箱小黑屋的结果返回', json_response) return json_response async def run(): while True: printer.info(["检查宝箱状态"], True) json_rsp = await GetAward() if json_rsp is None or json_rsp['code'] == -10017: sleeptime = (utils.seconds_until_tomorrow() + 300) await asyncio.sleep(sleeptime) elif not json_rsp['code']: printer.info(["# 打开了宝箱"]) elif json_rsp['code'] == 400: print('小黑屋') await asyncio.sleep(3600) continue print('小黑屋, 暴力测试中') tasklist = [] for i in range(60): task = asyncio.ensure_future(GetAward_black()) tasklist.append(task) await asyncio.wait(tasklist, return_when=asyncio.FIRST_COMPLETED) json_rsp = await GetAward() sleeptime = 3 * 60 + 5 await asyncio.sleep(sleeptime) else: printer.info(["# 继续等待宝箱冷却..."]) # 未来如果取消了这个东西就睡眠185s,否则精确睡眠 # surplus里面是min,float格式 sleeptime = (json_rsp['data'].get('surplus', 3)) * 60 + 5 await asyncio.sleep(sleeptime) ================================================ FILE: Tasks.py ================================================ from online_net import OnlineNet import asyncio from configloader import ConfigLoader import utils import printer from bilitimer import BiliTimer import random import re import json # 获取每日包裹奖励 async def Daily_bag(): json_response = await OnlineNet().req('get_dailybag') # no done code for i in json_response['data']['bag_list']: printer.info([f'# 获得包裹 {i["bag_name"]}']) BiliTimer.call_after(Daily_bag, 21600) # 签到功能 async def DoSign(): # -500 done temp = await OnlineNet().req('get_dosign') printer.info([f'# 签到状态: {temp["msg"]}']) if temp['code'] == -500 and '已' in temp['msg']: sleeptime = (utils.seconds_until_tomorrow() + 300) else: sleeptime = 350 BiliTimer.call_after(DoSign, sleeptime) # 领取每日任务奖励 async def Daily_Task(): # -400 done/not yet json_response2 = await OnlineNet().req('get_dailytask') printer.info([f'# 双端观看直播: {json_response2["msg"]}']) if json_response2['code'] == -400 and '已' in json_response2['msg']: sleeptime = (utils.seconds_until_tomorrow() + 300) else: sleeptime = 350 BiliTimer.call_after(Daily_Task, sleeptime) async def Sign1Group(i1, i2): json_response = await OnlineNet().req('assign_group', i1, i2) if not json_response['code']: data = json_response['data'] if data['status']: printer.info([f'# 应援团 {i1} 已应援过']) else: printer.info([f'# 应援团 {i1} 应援成功,获得{data["add_num"]}点亲密度']) # 应援团签到 async def link_sign(): json_rsp = await OnlineNet().req('get_grouplist') list_check = json_rsp['data']['list'] for i in list_check: asyncio.ensure_future(Sign1Group(i['group_id'], i['owner_uid'])) BiliTimer.call_after(link_sign, 21600) async def send_expiring_gift(): task_control = ConfigLoader().dic_user['task_control'] if task_control['clean-expiring-gift']: argvs = await utils.fetch_bag_list(show=False) roomID = task_control['clean-expiring-gift2room'] time_set = task_control['set-expiring-time'] list_gift = [] for i in argvs: left_time = i[3] # 剩余时间少于半天时自动送礼 if left_time is not None and 0 < int(left_time) < time_set: list_gift.append(i[:3]) if list_gift: print('发现即将过期的礼物', list_gift) if task_control['clean_expiring_gift2all_medal']: print('正在投递其他勋章') list_medal = await utils.fetch_medal(show=False) list_gift = await full_intimate(list_gift, list_medal) print('正在清理过期礼物到指定房间') for i in list_gift: giftID = i[0] giftNum = i[1] bagID = i[2] await utils.send_gift_web(roomID, giftNum, bagID, giftID) else: print('未发现即将过期的礼物') async def send_medal_gift(): list_medal = [] task_control = ConfigLoader().dic_user['task_control'] if task_control['send2wearing-medal']: list_medal = await utils.WearingMedalInfo() if not list_medal: print('暂未佩戴任何勋章') if task_control['send2medal']: list_medal += await utils.fetch_medal(False, task_control['send2medal']) # print(list_medal) print('正在投递勋章') temp = await utils.fetch_bag_list(show=False) # print(temp) list_gift = [] for i in temp: gift_id = int(i[0]) left_time = i[3] if (gift_id not in [4, 3, 9, 10]) and left_time is not None: list_gift.append(i[:3]) await full_intimate(list_gift, list_medal) async def send_gift(): await send_medal_gift() await send_expiring_gift() BiliTimer.call_after(send_gift, 21600) async def full_intimate(list_gift, list_medal): json_res = await OnlineNet().req('gift_list') dic_gift = {j['id']: int(j['price'] / 100) for j in json_res['data']} for roomid, score_wanted, medal_name in list_medal: sum_score = 0 for i in list_gift: gift_id, gift_num, bag_id = i price = dic_gift[gift_id] left_score = score_wanted - sum_score if price * gift_num <= left_score: num_wanted = gift_num elif left_score >= price: num_wanted = int(left_score / price) else: num_wanted = 0 await utils.send_gift_web(roomid, num_wanted, bag_id, gift_id) i[1] -= num_wanted score = price * num_wanted sum_score += score printer.info([f'# 对{medal_name}共送出亲密度为{sum_score}的礼物']) return [i for i in list_gift if i[1]] async def doublegain_coin2silver(): if ConfigLoader().dic_user['task_control']['doublegain_coin2silver']: json_response0 = await OnlineNet().req('request_doublegain_coin2silver') json_response1 = await OnlineNet().req('request_doublegain_coin2silver') print(json_response0['msg'], json_response1['msg']) BiliTimer.call_after(doublegain_coin2silver, 21600) async def sliver2coin(): if ConfigLoader().dic_user['task_control']['silver2coin']: # 403 done # json_response1 = await OnlineNet().req('silver2coin_app') json_response = await OnlineNet().req('silver2coin_web') printer.info([f'# {json_response["msg"]}']) if json_response['code'] == 403 and '最多' in json_response['msg']: finish_web = True else: finish_web = False if finish_web: sleeptime = (utils.seconds_until_tomorrow() + 300) BiliTimer.call_after(sliver2coin, sleeptime) return else: BiliTimer.call_after(sliver2coin, 350) return BiliTimer.call_after(sliver2coin, 21600) async def GetVideoExp(list_topvideo): print('开始获取视频观看经验') aid = random.choice(list_topvideo) cid = await utils.GetVideoCid(aid) await OnlineNet().req('Heartbeat', aid, cid) async def GiveCoinTask(coin_remain, list_topvideo): i = 0 while coin_remain > 0: i += 1 if i > 20: print('本次可投票视频获取量不足') return aid = random.choice(list_topvideo) rsp = await utils.GiveCoin2Av(aid, 1) if rsp is None: break elif rsp: coin_remain -= 1 async def GetVideoShareExp(list_topvideo): print('开始获取视频分享经验') aid = random.choice(list_topvideo) await OnlineNet().req('DailyVideoShare', aid) async def BiliMainTask(): task_control = ConfigLoader().dic_user['task_control'] login, watch_av, num, share_av = await utils.GetRewardInfo() if task_control['fetchrule'] == 'bilitop': list_topvideo = await utils.GetTopVideoList() else: list_topvideo = await utils.fetch_uper_video(task_control['mid']) if (not login) or not watch_av: await GetVideoExp(list_topvideo) coin_sent = num / 10 coin_set = min(task_control['givecoin'], 5) coin_remain = coin_set - coin_sent await GiveCoinTask(coin_remain, list_topvideo) if not share_av: await GetVideoShareExp(list_topvideo) # b站傻逼有记录延迟,3点左右成功率高一点 BiliTimer.call_after(BiliMainTask, utils.seconds_until_tomorrow() + 10800) async def check(id): # 3放弃 # 2 否 voterule # 4 删除 votedelete # 1 封杀 votebreak text_rsp = await OnlineNet().req('req_check_voted', id) pattern = re.compile(r'\((.+)\)') match = pattern.findall(text_rsp) temp = json.loads(match[0]) data = temp['data'] votebreak = data['voteBreak'] voteDelete = data['voteDelete'] voteRule = data['voteRule'] voted = votebreak+voteDelete+voteRule percent = (voteRule / voted) if voted else 0 print(f'\"{data["originContent"]}\"') print('该案件目前已投票', voted) print('认为言论合理比例', percent) return voted, percent def judge_case(voted, percent): vote = None if voted >= 300: # 认为这里可能出现了较多分歧,抬一手 if percent >= 0.4: vote = 2 elif percent <= 0.25: vote = 4 elif voted >= 150: if percent >= 0.9: vote = 2 elif percent <= 0.1: vote = 4 elif voted >= 50: if percent >= 0.97: vote = 2 elif percent <= 0.03: vote = 4 # 抬一手 if vote is None and voted >= 400: vote = 2 return vote async def judge(): num_case = 0 num_voted = 0 while True: temp = await OnlineNet().req('req_fetch_case') if not temp['code']: id = temp['data']['id'] num_case += 1 else: print('本次未获取到案件') break wait_time = 0 min_percent = 1 max_percent = 0 while True: voted, percent = await check(id) vote = judge_case(voted, percent) if voted >= 50: min_percent = min(min_percent, percent) max_percent = max(max_percent, percent) print('统计投票波动情况', max_percent, min_percent) if vote is not None: break elif wait_time >= 1200: print('进入二次判定') # 如果case判定中,波动很小,则表示趋势基本一致 if 0 <= max_percent - min_percent <= 0.1 and voted > 200: future_voted = voted + 100 vote0 = judge_case(future_voted, max_percent) vote1 = judge_case(future_voted, min_percent) vote = vote0 if vote0 == vote1 else None print('二次判定结果', vote) break else: sleep_time = 180 if voted < 300 else 60 printer.info([f'案件{id}暂时无法判定,在{sleep_time}后重新尝试'], True) await asyncio.sleep(sleep_time) wait_time += sleep_time if vote is None: num_voted -= 1 vote = 3 vote_info = '作废票' if vote == 3 else '有效票' print('该案件的投票决策', id, vote, vote_info) json_rsp = await OnlineNet().req('req_vote_case', id, vote) if not json_rsp['code']: print('该案件的投票结果', id, '投票成功') num_voted += 1 else: print('该案件的投票结果', id, '投票失败,请反馈作者') print('______________________________________________') printer.info([f'风纪委员会共获取{num_case}件案例,其中有效投票{num_voted}件'], True) BiliTimer.call_after(judge, 3600) def init(): BiliTimer.call_after(sliver2coin, 0) BiliTimer.call_after(doublegain_coin2silver, 0) BiliTimer.call_after(DoSign, 0) BiliTimer.call_after(Daily_bag, 0) BiliTimer.call_after(Daily_Task, 0) BiliTimer.call_after(link_sign, 0) BiliTimer.call_after(send_gift, 0) BiliTimer.call_after(BiliMainTask, 0) BiliTimer.call_after(judge, 0) ================================================ FILE: bili_console.py ================================================ import sys import utils from statistics import Statistics from connect import connect import printer from configloader import ConfigLoader from rafflehandler import Rafflehandler import rafflehandler import OnlineHeart import asyncio from cmd import Cmd def fetch_real_roomid(roomid): if roomid: real_roomid = [[roomid], utils.check_room] else: real_roomid = ConfigLoader().dic_user['other_control']['default_monitor_roomid'] return real_roomid class Biliconsole(Cmd): prompt = '' def __init__(self, loop): self.loop = loop Cmd.__init__(self) def guide_of_console(self): print(' ___________________ ') print('|   欢迎使用本控制台        |') print('| 1 输出本次抽奖统计        |') print('| 2 查看目前拥有礼物的统计     |') print('| 3 查看持有勋章状态        |') print('| 4 获取直播个人的基本信息     |') print('| 5 检查今日任务的完成情况     |') print('| 6 模拟电脑网页端发送弹幕     |') print('| 7 直播间的长短号码的转化     |') print('| 8 手动送礼物到指定直播间     |') print('| 9 切换监听的直播间        |') print('|10 控制弹幕的开关         |') print('|11 房间号码查看主播        |') print('|12 当前拥有的扭蛋币        |') print('|13 开扭蛋币(一、十、百)     |') print('|16 尝试一次实物抽奖        |') print('  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ') def default(self, line): self.guide_of_console() def emptyline(self): self.guide_of_console() def do_1(self, line): Statistics.getlist() def do_2(self, line): self.append2list_console(utils.fetch_bag_list) def do_3(self, line): self.append2list_console(utils.fetch_medal) def do_4(self, line): self.append2list_console(utils.fetch_user_info) def do_5(self, line): self.append2list_console(utils.check_taskinfo) def do_6(self, line): msg = input('请输入要发送的信息:') roomid = input('请输入要发送的房间号:') real_roomid = fetch_real_roomid(roomid) self.append2list_console([[msg, real_roomid], utils.send_danmu_msg_web]) def do_7(self, line): roomid = input('请输入要转化的房间号:') if not roomid: roomid = ConfigLoader().dic_user['other_control']['default_monitor_roomid'] self.append2list_console([[roomid], utils.check_room]) def do_8(self, line): self.append2list_console([[True], utils.fetch_bag_list]) bagid = input('请输入要发送的礼物编号:') # print('是谁', giftid) giftnum = int(input('请输入要发送的礼物数目:')) roomid = input('请输入要发送的房间号:') real_roomid = fetch_real_roomid(roomid) self.append2list_console([[real_roomid, giftnum, bagid], utils.send_gift_web]) def do_9(self, line): roomid = input('请输入roomid') real_roomid = fetch_real_roomid(roomid) self.append2list_console([[real_roomid], connect.reconnect]) def do_10(self, line): new_words = input('弹幕控制') if new_words == 'T': printer.control_printer(True, None) else: printer.control_printer(False, None) def do_11(self, line): roomid = input('请输入roomid') real_roomid = fetch_real_roomid(roomid) self.append2list_console([[real_roomid], utils.fetch_liveuser_info]) def do_12(self, line): self.append2list_console(utils.fetch_capsule_info) def do_13(self, line): count = input('请输入要开的扭蛋数目(1或10或100)') self.append2list_console([[count], utils.open_capsule]) def do_14(self, line): if sys.platform == 'ios': roomid = input('请输入roomid') real_roomid = fetch_real_roomid(roomid) self.append2list_console([[real_roomid], utils.watch_living_video]) return print('仅支持ios') def do_15(self, line): self.append2list_console(utils.TitleInfo) def do_16(self, line): self.append2list_console(OnlineHeart.draw_lottery) def do_17(self, line): new_words = input('debug控制') if new_words == 'T': printer.control_printer(None, True) else: printer.control_printer(None, True) def do_18(self, line): video_id = input('请输入av号') num = input('输入数目') self.append2list_console([[int(video_id), int(num)], utils.GiveCoin2Av]) def do_19(self, line): try: roomid = int(input('输入roomid')) self.append2list_console([[(roomid,), rafflehandler.handle_1_room_guard], rafflehandler.Rafflehandler.Put2Queue_wait]) except: pass def do_check(self, line): Rafflehandler.getlist() Statistics.checklist() def append2list_console(self, request): asyncio.run_coroutine_threadsafe(self.excute_async(request), self.loop) # inst.loop.call_soon_threadsafe(inst.queue_console.put_nowait, request) async def excute_async(self, i): if isinstance(i, list): # 对10号单独简陋处理 for j in range(len(i[0])): if isinstance(i[0][j], list): # print('检测') i[0][j] = await i[0][j][1](*(i[0][j][0])) if i[1] == 'normal': i[2](*i[0]) else: await i[1](*i[0]) else: await i() ================================================ FILE: bilibili.py ================================================ import sys from configloader import ConfigLoader import hashlib import time import requests import base64 import aiohttp import asyncio import random import json try: from PIL import Image except ImportError: Image = None from io import BytesIO def CurrentTime(): currenttime = int(time.time()) return str(currenttime) def randomint(): return ''.join(str(random.randint(0, 9)) for _ in range(17)) def cnn_captcha(content): img = base64.b64encode(content) url = "http://47.95.255.188:5000/code" data = {"image": img} rsp = requests.post(url, data=data) captcha = rsp.text print(f'此次登录出现验证码,识别结果为{captcha}') return captcha def input_captcha(content): if Image is not None: img = Image.open(BytesIO(content)) # img.thumbnail(size) img.show() captcha = input('手动输入验证码') else: captcha = input('您并没有安装pillow模块,但仍然选择了手动输入,那就输呀:') return captcha base_url = 'https://api.live.bilibili.com' class bilibili(): __slots__ = ('dic_bilibili', 'var_bili_session', 'app_params', 'var_other_session', 'var_login_session') instance = None def __new__(cls, *args, **kw): if not cls.instance: cls.instance = super(bilibili, cls).__new__(cls, *args, **kw) cls.instance.dic_bilibili = ConfigLoader().dic_bilibili dic_bilibili = ConfigLoader().dic_bilibili cls.instance.var_bili_session = None cls.instance.var_other_session = None cls.instance.var_login_session = None cls.instance.app_params = f'actionKey={dic_bilibili["actionKey"]}&appkey={dic_bilibili["appkey"]}&build={dic_bilibili["build"]}&device={dic_bilibili["device"]}&mobi_app={dic_bilibili["mobi_app"]}&platform={dic_bilibili["platform"]}' return cls.instance @property def bili_session(self): if self.var_bili_session is None: self.var_bili_session = aiohttp.ClientSession() # print(0) return self.var_bili_session @property def other_session(self): if self.var_other_session is None: self.var_other_session = aiohttp.ClientSession() # print(0) return self.var_other_session @property def login_session(self): if self.var_login_session is None: self.var_login_session = requests.Session() # print(0) return self.var_login_session def calc_sign(self, str): str = f'{str}{self.dic_bilibili["app_secret"]}' sign = hashlib.md5(str.encode('utf-8')).hexdigest() return sign @staticmethod def load_session(dic): # print(dic) inst = bilibili.instance for i in dic.keys(): inst.dic_bilibili[i] = dic[i] if i == 'cookie': inst.dic_bilibili['pcheaders']['cookie'] = dic[i] inst.dic_bilibili['appheaders']['cookie'] = dic[i] def login_session_post(self, url, headers=None, data=None, params=None): while True: try: # print(self.login_session.cookies, url) rsp = self.login_session.post(url, headers=headers, data=data, params=params) if rsp.status_code == requests.codes.ok and rsp.content: return rsp elif rsp.status_code == 403: print('403频繁') except: # print('当前网络不好,正在重试,请反馈开发者!!!!') print(sys.exc_info()[0], sys.exc_info()[1], url) continue def login_session_get(self, url, headers=None, data=None, params=None): while True: try: # print(self.login_session.cookies, url) rsp = self.login_session.get(url, headers=headers, data=data, params=params) if rsp.status_code == requests.codes.ok and rsp.content: return rsp elif rsp.status_code == 403: print('403频繁') except: # print('当前网络不好,正在重试,请反馈开发者!!!!') print(sys.exc_info()[0], sys.exc_info()[1], url) continue async def get_json_rsp(self, rsp, url): if rsp.status == 200: # json_rsp = await rsp.json(content_type=None) data = await rsp.read() json_rsp = json.loads(data) if isinstance(json_rsp, dict) and 'code' in json_rsp: code = json_rsp['code'] if code == 1024: print('b站炸了,暂停所有请求1.5s后重试,请耐心等待') await asyncio.sleep(1.5) return None elif code == 3: print('api错误,稍后重试,请反馈给作者') print(json_rsp) await asyncio.sleep(1) return 3 return json_rsp elif rsp.status == 403: print('403频繁', url) return None async def get_text_rsp(self, rsp, url): if rsp.status == 200: return await rsp.text() elif rsp.status == 403: print('403频繁', url) return None async def bili_session_post(self, url, headers=None, data=None, params=None): while True: try: async with self.bili_session.post(url, headers=headers, data=data, params=params) as rsp: json_rsp = await self.get_json_rsp(rsp, url) if json_rsp is not None: return json_rsp except: # print('当前网络不好,正在重试,请反馈开发者!!!!') print(sys.exc_info()[0], sys.exc_info()[1], url) continue async def other_session_get(self, url, headers=None, data=None, params=None): while True: try: async with self.other_session.get(url, headers=headers, data=data, params=params) as rsp: json_rsp = await self.get_json_rsp(rsp, url) if json_rsp is not None: return json_rsp except: # print('当前网络不好,正在重试,请反馈开发者!!!!') print(sys.exc_info()[0], sys.exc_info()[1], url) continue async def other_session_post(self, url, headers=None, data=None, params=None): while True: try: async with self.other_session.post(url, headers=headers, data=data, params=params) as rsp: json_rsp = await self.get_json_rsp(rsp, url) if json_rsp is not None: return json_rsp except: # print('当前网络不好,正在重试,请反馈开发者!!!!') print(sys.exc_info()[0], sys.exc_info()[1], url) continue async def bili_session_get(self, url, headers=None, data=None, params=None): while True: try: async with self.bili_session.get(url, headers=headers, data=data, params=params) as rsp: json_rsp = await self.get_json_rsp(rsp, url) if json_rsp is not None: return json_rsp except: # print('当前网络不好,正在重试,请反馈开发者!!!!') print(sys.exc_info()[0], sys.exc_info()[1], url) continue async def session_text_get(self, url, headers=None, data=None, params=None): while True: try: async with self.other_session.get(url, headers=headers, data=data, params=params) as rsp: text_rsp = await self.get_text_rsp(rsp, url) if text_rsp is not None: return text_rsp except: # print('当前网络不好,正在重试,请反馈开发者!!!!') print(sys.exc_info()[0], sys.exc_info()[1], url) continue @staticmethod async def request_playurl(cid): inst = bilibili.instance # cid real_roomid # url = 'http://api.live.bilibili.com/room/v1/Room/playUrl?' url = f'{base_url}/api/playurl?device=phone&platform=ios&scale=3&build=10000&cid={cid}&otype=json&platform=h5' json_rsp = await inst.bili_session_get(url) return json_rsp @staticmethod async def request_search_liveuser(name): inst = bilibili.instance search_url = f'https://search.bilibili.com/api/search?search_type=live_user&keyword={name}&page=1' json_rsp = await inst.other_session_get(search_url) return json_rsp @staticmethod async def request_search_biliuser(name): inst = bilibili.instance search_url = f"https://search.bilibili.com/api/search?search_type=bili_user&keyword={name}" json_rsp = await inst.other_session_get(search_url) return json_rsp @staticmethod async def request_fetch_capsule(): inst = bilibili.instance url = f"{base_url}/api/ajaxCapsule" json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def request_open_capsule(count): inst = bilibili.instance url = f"{base_url}/api/ajaxCapsuleOpen" data = { 'type': 'normal', "count": count, "csrf_token": inst.dic_bilibili['csrf'] } json_rsp = await inst.bili_session_post(url, data=data, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod def request_logout(): inst = bilibili.instance list_url = f'access_key={inst.dic_bilibili["access_key"]}&access_token={inst.dic_bilibili["access_key"]}&{inst.app_params}&ts={CurrentTime()}' list_cookie = inst.dic_bilibili['cookie'].split(';') params = ('&'.join(sorted(list_url.split('&') + list_cookie))) sign = inst.calc_sign(params) true_url = f'https://passport.bilibili.com/api/v2/oauth2/revoke' data = f'{params}&sign={sign}' appheaders = {**(inst.dic_bilibili['appheaders']), 'cookie': ''} rsp = inst.login_session_post(true_url, params=data, headers=appheaders) print(rsp.json()) return rsp # 1:900兑换 @staticmethod async def request_doublegain_coin2silver(): inst = bilibili.instance # url: "/exchange/coin2silver", data = {'coin': 10} url = f"{base_url}/exchange/coin2silver" json_rsp = await inst.bili_session_post(url, data=data, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def post_watching_history(room_id): inst = bilibili.instance data = { "room_id": room_id, "csrf_token": inst.dic_bilibili['csrf'] } url = f"{base_url}/room/v1/Room/room_entry_action" json_rsp = await inst.bili_session_post(url, data=data, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def silver2coin_web(): inst = bilibili.instance url = f"{base_url}/pay/v1/Exchange/silver2coin" data = { "platform": 'pc', "csrf_token": inst.dic_bilibili['csrf'] } json_rsp = await inst.bili_session_post(url, headers=inst.dic_bilibili['pcheaders'], data=data) return json_rsp @staticmethod async def silver2coin_app(): inst = bilibili.instance temp_params = f'access_key={inst.dic_bilibili["access_key"]}&{inst.app_params}&ts={CurrentTime()}' sign = inst.calc_sign(temp_params) app_url = f"{base_url}/AppExchange/silver2coin?{temp_params}&sign={sign}" json_rsp = await inst.bili_session_post(app_url, headers=inst.dic_bilibili['appheaders']) return json_rsp @staticmethod async def request_fetch_fan(real_roomid, uid): inst = bilibili.instance url = f'{base_url}/rankdb/v1/RoomRank/webMedalRank?roomid={real_roomid}&ruid={uid}' json_rsp = await inst.bili_session_get(url) return json_rsp @staticmethod async def request_check_room(roomid): inst = bilibili.instance url = f"{base_url}/room/v1/Room/room_init?id={roomid}" json_rsp = await inst.bili_session_get(url) return json_rsp @staticmethod async def request_fetch_bag_list(): inst = bilibili.instance url = f"{base_url}/gift/v2/gift/bag_list" json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def request_check_taskinfo(): inst = bilibili.instance url = f'{base_url}/i/api/taskInfo' json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def request_send_gift_web(giftid, giftnum, bagid, ruid, biz_id): inst = bilibili.instance url = f"{base_url}/gift/v2/live/bag_send" data = { 'uid': inst.dic_bilibili['uid'], 'gift_id': giftid, 'ruid': ruid, 'gift_num': giftnum, 'bag_id': bagid, 'platform': 'pc', 'biz_code': 'live', 'biz_id': biz_id, 'rnd': CurrentTime(), 'storm_beat_id': '0', 'metadata': '', 'price': '0', 'csrf_token': inst.dic_bilibili['csrf'] } json_rsp = await inst.bili_session_post(url, headers=inst.dic_bilibili['pcheaders'], data=data) return json_rsp @staticmethod async def request_fetch_user_info(): inst = bilibili.instance url = f"{base_url}/i/api/liveinfo" json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def request_fetch_user_infor_ios(): inst = bilibili.instance temp_params = f'access_key={inst.dic_bilibili["access_key"]}&platform=ios' url = f'{base_url}/mobile/getUser?{temp_params}' json_rsp = await inst.bili_session_get(url) return json_rsp @staticmethod async def request_fetch_liveuser_info(real_roomid): inst = bilibili.instance url = f'{base_url}/live_user/v1/UserInfo/get_anchor_in_room?roomid={real_roomid}' json_rsp = await inst.bili_session_get(url) return json_rsp @staticmethod async def request_load_img(url): return await bilibili.instance.other_session.get(url) @staticmethod async def request_send_danmu_msg_web(msg, roomId): inst = bilibili.instance url = f'{base_url}/msg/send' data = { 'color': '16777215', 'fontsize': '25', 'mode': '1', 'msg': msg, 'rnd': '0', 'roomid': int(roomId), 'csrf_token': inst.dic_bilibili['csrf'], 'csrf': inst.dic_bilibili['csrf'] } json_rsp = await inst.bili_session_post(url, headers=inst.dic_bilibili['pcheaders'], data=data) return json_rsp @staticmethod async def request_fetchmedal(): inst = bilibili.instance url = f'{base_url}/i/api/medal?page=1&pageSize=50' json_rsp = await inst.bili_session_post(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def ReqWearingMedal(): inst = bilibili.instance url = f'{base_url}/live_user/v1/UserInfo/get_weared_medal' data = { 'uid': inst.dic_bilibili['uid'], 'csrf_token': '' } json_rsp = await inst.bili_session_post(url, data=data, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def ReqTitleInfo(): inst = bilibili.instance temp_params = f'access_key={inst.dic_bilibili["access_key"]}&{inst.app_params}' sign = inst.calc_sign(temp_params) url = f'{base_url}/appUser/myTitleList?{temp_params}&sign={sign}' json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['appheaders']) return json_rsp @staticmethod def request_getkey(): inst = bilibili.instance url = 'https://passport.bilibili.com/api/oauth2/getKey' temp_params = f'appkey={inst.dic_bilibili["appkey"]}' sign = inst.calc_sign(temp_params) params = {'appkey': inst.dic_bilibili['appkey'], 'sign': sign} response = inst.login_session_post(url, data=params) return response @staticmethod def normal_login(username, password, captcha=None): inst = bilibili.instance if captcha is None: captcha = '' temp_params = f'actionKey={inst.dic_bilibili["actionKey"]}&appkey={inst.dic_bilibili["appkey"]}&build={inst.dic_bilibili["build"]}&captcha={captcha}&device={inst.dic_bilibili["device"]}&mobi_app={inst.dic_bilibili["mobi_app"]}&password={password}&platform={inst.dic_bilibili["platform"]}&username={username}' sign = inst.calc_sign(temp_params) payload = f'{temp_params}&sign={sign}' url = "https://passport.bilibili.com/api/v2/oauth2/login" response = inst.login_session_post(url, params=payload) return response @staticmethod def get_captcha(username, password): inst = bilibili.instance # with requests.Session() as s: url = "https://passport.bilibili.com/captcha" res = inst.login_session_get(url) # print(res.content) # print(res.content) captcha = cnn_captcha(res.content) return captcha @staticmethod def request_check_token(): inst = bilibili.instance list_url = f'access_key={inst.dic_bilibili["access_key"]}&{inst.app_params}&ts={CurrentTime()}' list_cookie = inst.dic_bilibili['cookie'].split(';') params = ('&'.join(sorted(list_url.split('&') + list_cookie))) sign = inst.calc_sign(params) true_url = f'https://passport.bilibili.com/api/v2/oauth2/info?{params}&sign={sign}' response1 = inst.login_session_get(true_url, headers=inst.dic_bilibili['appheaders']) return response1 @staticmethod def request_refresh_token(): inst = bilibili.instance list_url = f'access_key={inst.dic_bilibili["access_key"]}&access_token={inst.dic_bilibili["access_key"]}&{inst.app_params}&refresh_token={inst.dic_bilibili["refresh_token"]}&ts={CurrentTime()}' list_cookie = inst.dic_bilibili['cookie'].split(';') params = ('&'.join(sorted(list_url.split('&') + list_cookie))) sign = inst.calc_sign(params) payload = f'{params}&sign={sign}' # print(payload) url = f'https://passport.bilibili.com/api/v2/oauth2/refresh_token' response1 = inst.login_session_post(url, headers=inst.dic_bilibili['appheaders'], params=payload) return response1 @staticmethod async def get_giftlist_of_storm(roomid): inst = bilibili.instance get_url = f"{base_url}/lottery/v1/Storm/check?roomid={roomid}" json_rsp = await inst.bili_session_get(get_url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_gift_of_storm(id): inst = bilibili.instance storm_url = f'{base_url}/lottery/v1/Storm/join' payload = { "id": id, "color": "16777215", "captcha_token": "", "captcha_phrase": "", "token": "", "csrf_token": inst.dic_bilibili['csrf']} json_rsp = await inst.bili_session_post(storm_url, data=payload, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_gift_of_events_web(text1, text2, raffleid): inst = bilibili.instance headers = { **(inst.dic_bilibili['pcheaders']), 'referer': text2 } pc_url = f'{base_url}/activity/v1/Raffle/join?roomid={text1}&raffleId={raffleid}' json_rsp = await inst.bili_session_get(pc_url, headers=headers) return json_rsp @staticmethod async def get_gift_of_events_app(text1, raffleid): inst = bilibili.instance temp_params = f'access_key={inst.dic_bilibili["access_key"]}&actionKey={inst.dic_bilibili["actionKey"]}&appkey={inst.dic_bilibili["appkey"]}&build={inst.dic_bilibili["build"]}&device={inst.dic_bilibili["device"]}&event_type={raffleid}&mobi_app={inst.dic_bilibili["mobi_app"]}&platform={inst.dic_bilibili["platform"]}&room_id={text1}&ts={CurrentTime()}' # params = temp_params + inst.dic_bilibili['app_secret'] sign = inst.calc_sign(temp_params) true_url = f'{base_url}/YunYing/roomEvent?{temp_params}&sign={sign}' json_rsp = await inst.bili_session_get(true_url, headers=inst.dic_bilibili['appheaders']) return json_rsp @staticmethod async def get_gift_of_TV(real_roomid, TV_raffleid): inst = bilibili.instance url = f"{base_url}/gift/v3/smalltv/join" payload = { "roomid": real_roomid, "raffleId": TV_raffleid, "type": "Gift", "csrf_token": '' } json_rsp = await inst.bili_session_post(url, data=payload, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_gift_of_TV_app(real_roomid, raffle_id, raffle_type): inst = bilibili.instance url = f"{base_url}/gift/v4/smalltv/getAward" temp_params = f'access_key={inst.dic_bilibili["access_key"]}&{inst.app_params}&raffleId={raffle_id}&roomid={real_roomid}&ts={CurrentTime()}&type={raffle_type}' sign = inst.calc_sign(temp_params) payload = f'{temp_params}&sign={sign}' # print(payload) json_rsp = await inst.bili_session_post(url, params=payload, headers=inst.dic_bilibili['appheaders']) # print(json_rsp) return json_rsp @staticmethod async def get_gift_of_guard(roomid, id): inst = bilibili.instance join_url = f"{base_url}/lottery/v2/Lottery/join" data = { 'roomid': roomid, 'id': id, 'type': 'guard', 'csrf_token': inst.dic_bilibili['csrf'] } json_rsp = await inst.bili_session_post(join_url, data=data, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_giftlist_of_events(text1): inst = bilibili.instance # url = f'{base_url}/activity/v1/Raffle/check?roomid={text1}' temp_params = f'{base_url}/activity/v1/Common/mobileRoomInfo?access_key={inst.dic_bilibili["access_key"]}&{inst.app_params}&roomid={text1}&ts={CurrentTime()}' sign = inst.calc_sign(temp_params) url = f'{base_url}/activity/v1/Common/mobileRoomInfo?{temp_params}&sign={sign}' json_rsp = await bilibili.instance.bili_session_get(url, headers=inst.dic_bilibili['appheaders']) return json_rsp @staticmethod async def get_giftlist_of_TV(real_roomid): inst = bilibili.instance url = f"{base_url}/gift/v3/smalltv/check?roomid={real_roomid}" json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_giftlist_of_guard(roomid): inst = bilibili.instance true_url = f'{base_url}/lottery/v1/Lottery/check_guard?roomid={roomid}' json_rsp = await inst.bili_session_get(true_url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_activity_result(activity_roomid, activity_raffleid): inst = bilibili.instance url = f"{base_url}/activity/v1/Raffle/notice?roomid={activity_roomid}&raffleId={activity_raffleid}" json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_TV_result(TV_roomid, TV_raffleid): inst = bilibili.instance url = f"{base_url}/gift/v3/smalltv/notice?type=small_tv&raffleId={TV_raffleid}" json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def pcpost_heartbeat(): inst = bilibili.instance url = f'{base_url}/User/userOnlineHeart' json_rsp = await inst.bili_session_post(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp # 发送app心跳包 @staticmethod async def apppost_heartbeat(): inst = bilibili.instance time = CurrentTime() temp_params = f'access_key={inst.dic_bilibili["access_key"]}&{inst.app_params}&ts={time}' sign = inst.calc_sign(temp_params) url = f'{base_url}/mobile/userOnlineHeart?{temp_params}&sign={sign}' payload = {'roomid': 23058, 'scale': 'xhdpi'} json_rsp = await inst.bili_session_post(url, data=payload, headers=inst.dic_bilibili['appheaders']) return json_rsp # 心跳礼物 @staticmethod async def heart_gift(): inst = bilibili.instance url = f"{base_url}/gift/v2/live/heart_gift_receive?roomid=3&area_v2_id=34" json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_lotterylist(i): inst = bilibili.instance url = f"{base_url}/lottery/v1/box/getStatus?aid={i}" json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_gift_of_lottery(i, g): inst = bilibili.instance url1 = f'{base_url}/lottery/v1/box/draw?aid={i}&number={g + 1}' json_rsp = await inst.bili_session_get(url1, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_time_about_silver(): inst = bilibili.instance time = CurrentTime() temp_params = f'access_key={inst.dic_bilibili["access_key"]}&{inst.app_params}&ts={time}' sign = inst.calc_sign(temp_params) GetTask_url = f'{base_url}/mobile/freeSilverCurrentTask?{temp_params}&sign={sign}' json_rsp = await inst.bili_session_get(GetTask_url, headers=inst.dic_bilibili['appheaders']) return json_rsp @staticmethod async def get_silver(timestart, timeend): inst = bilibili.instance time = CurrentTime() temp_params = f'access_key={inst.dic_bilibili["access_key"]}&{inst.app_params}&time_end={timeend}&time_start={timestart}&ts={time}' sign = inst.calc_sign(temp_params) url = f'{base_url}/mobile/freeSilverAward?{temp_params}&sign={sign}' json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['appheaders']) return json_rsp @staticmethod async def get_dailybag(): inst = bilibili.instance url = f'{base_url}/gift/v2/live/receive_daily_bag' json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_dosign(): inst = bilibili.instance url = f'{base_url}/sign/doSign' json_rsp = await inst.bili_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def get_dailytask(): inst = bilibili.instance url = f'{base_url}/activity/v1/task/receive_award' payload2 = {'task_id': 'double_watch_task'} json_rsp = await inst.bili_session_post(url, data=payload2, headers=inst.dic_bilibili['appheaders']) return json_rsp @staticmethod async def get_grouplist(): inst = bilibili.instance url = "https://api.vc.bilibili.com/link_group/v1/member/my_groups" json_rsp = await inst.other_session_get(url, headers=inst.dic_bilibili['pcheaders']) return json_rsp @staticmethod async def assign_group(i1, i2): inst = bilibili.instance temp_params = f'access_key={inst.dic_bilibili["access_key"]}&actionKey={inst.dic_bilibili["actionKey"]}&appkey={inst.dic_bilibili["appkey"]}&build={inst.dic_bilibili["build"]}&device={inst.dic_bilibili["device"]}&group_id={i1}&mobi_app={inst.dic_bilibili["mobi_app"]}&owner_id={i2}&platform={inst.dic_bilibili["platform"]}&ts={CurrentTime()}' sign = inst.calc_sign(temp_params) url = f'https://api.vc.bilibili.com/link_setting/v1/link_setting/sign_in?{temp_params}&sign={sign}' json_rsp = await inst.other_session_get(url, headers=inst.dic_bilibili['appheaders']) return json_rsp @staticmethod async def gift_list(): url = f"{base_url}/gift/v3/live/gift_config" res = await bilibili.instance.bili_session_get(url) return res @staticmethod async def req_realroomid(areaid): url = f'{base_url}/room/v1/area/getRoomList?platform=web&parent_area_id={areaid}&cate_id=0&area_id=0&sort_type=online&page=1&page_size=30' json_rsp = await bilibili.instance.bili_session_get(url) return json_rsp @staticmethod async def req_room_init(roomid): url = f'{base_url}/room/v1/Room/room_init?id={roomid}' json_rsp = await bilibili.instance.bili_session_get(url) return json_rsp @staticmethod async def ReqRoomInfo(roomid): inst = bilibili.instance url = f"{base_url}/room/v1/Room/get_info?room_id={roomid}" res = await inst.bili_session_get(url) return res async def ReqGiveCoin2Av(self, video_id, num): url = 'https://api.bilibili.com/x/web-interface/coin/add' pcheaders = { **(self.dic_bilibili['pcheaders']), 'referer': f'https://www.bilibili.com/video/av{video_id}' } data = { 'aid': video_id, 'multiply': num, 'cross_domain': 'true', 'csrf': self.dic_bilibili['csrf'] } json_rsp = await self.other_session_post(url, headers=pcheaders, data=data) return json_rsp async def Heartbeat(self, aid, cid): url = 'https://api.bilibili.com/x/report/web/heartbeat' data = {'aid': aid, 'cid': cid, 'mid': self.dic_bilibili['uid'], 'csrf': self.dic_bilibili['csrf'], 'played_time': 0, 'realtime': 0, 'start_ts': int(time.time()), 'type': 3, 'dt': 2, 'play_type': 1} json_rsp = await self.other_session_post(url, data=data, headers=self.dic_bilibili['pcheaders']) return json_rsp async def ReqMasterInfo(self): url = 'https://account.bilibili.com/home/reward' json_rsp = await self.other_session_get(url, headers=self.dic_bilibili['pcheaders']) return json_rsp async def ReqVideoCid(self, video_aid): url = f'https://www.bilibili.com/widget/getPageList?aid={video_aid}' json_rsp = await self.other_session_get(url) return json_rsp async def DailyVideoShare(self, video_aid): url = 'https://api.bilibili.com/x/web-interface/share/add' data = {'aid': video_aid, 'jsonp': 'jsonp', 'csrf': self.dic_bilibili['csrf']} json_rsp = await self.other_session_post(url, data=data, headers=self.dic_bilibili['pcheaders']) return json_rsp async def req_fetch_uper_video(self, mid, page): url = f'https://space.bilibili.com/ajax/member/getSubmitVideos?mid={mid}&pagesize=100&page={page}' json_rsp = await self.other_session_get(url) return json_rsp async def req_fetch_av(self): text_tsp = await self.session_text_get('https://www.bilibili.com/ranking/all/0/0/1/') return text_tsp async def req_vote_case(self, id, vote): url = 'http://api.bilibili.com/x/credit/jury/vote' payload = { "jsonp": "jsonp", "cid": id, "vote": vote, "content": "", "likes": "", "hates": "", "attr": "1", "csrf": ConfigLoader().dic_bilibili['csrf'] } json_rsp = await self.other_session_post(url, headers=self.dic_bilibili['pcheaders'], data=payload) return json_rsp async def req_fetch_case(self): url = 'http://api.bilibili.com/x/credit/jury/caseObtain' payload = { "jsonp": "jsonp", "csrf": ConfigLoader().dic_bilibili['csrf'] } json_rsp = await self.other_session_post(url, headers=self.dic_bilibili['pcheaders'], data=payload) return json_rsp async def req_check_voted(self, id): headers = { **(self.dic_bilibili['pcheaders']), "Referer": f'https://www.bilibili.com/judgement/vote/{id}', } url = f'https://api.bilibili.com/x/credit/jury/juryCase?jsonp=jsonp&callback=jQuery1720{randomint()}_{CurrentTime()}&cid={id}&_={CurrentTime()}' text_rsp = await self.session_text_get(url, headers=headers) # print(text_rsp) return text_rsp ================================================ FILE: bilitimer.py ================================================ import asyncio import time import printer def CurrentTime(): currenttime = int(time.time()) return currenttime class BiliTimer: __slots__ = ('loop',) instance = None def __new__(cls, loop=None): if not cls.instance: cls.instance = super(BiliTimer, cls).__new__(cls) cls.instance.loop = loop return cls.instance def excute_async(self, i): print('执行', i) asyncio.ensure_future(i[0](*i[1])) @staticmethod def call_after(func, delay): inst = BiliTimer.instance value = (func, ()) inst.loop.call_later(delay, inst.excute_async, value) @staticmethod def append2list_jobs(func, time_expected, tuple_values): inst = BiliTimer.instance current_time = CurrentTime() value = (func, tuple_values) inst.loop.call_later(time_expected-current_time, inst.excute_async, value) ================================================ FILE: conf/bilibili.toml ================================================ appkey = "1d8b6e7d45233436" actionKey = "appkey" build = "520001" device = "android" mobi_app = "android" platform = "android" app_secret = "560c52ccd288fed045859ed18bffd973" refresh_token = "" access_key = "" cookie = "" csrf = "" uid = "" [pcheaders] Accept = "application/json, text/plain, */*" User-Agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36" Accept-Language = "zh-CN,zh;q=0.9" accept-encoding = "gzip, deflate" cookie = "" [appheaders] User-Agent = "bili-universal/6570 CFNetwork/894 Darwin/17.4.0" Accept-encoding = "gzip" Buvid = "000ce0b9b9b4e342ad4f421bcae5e0ce" Display-ID = "146771405-1521008435" Accept-Language = "zh-CN" Accept = "text/html,application/xhtml+xml,*/*;q=0.8" Connection = "keep-alive" cookie = "" [account] username = "" password = "" [saved-session] access_key = "" cookie = "" csrf = "" uid = "" refresh_token = "" ================================================ FILE: conf/color.toml ================================================ [user-level] ul0 = "#646c7a" ul1 = "#969696" ul2 = "#969696" ul3 = "#969696" ul4 = "#969696" ul5 = "#969696" ul6 = "#969696" ul7 = "#969696" ul8 = "#969696" ul9 = "#969696" ul10 = "#969696" ul11 = "#61c05a" ul12 = "#61c05a" ul13 = "#61c05a" ul14 = "#61c05a" ul15 = "#61c05a" ul16 = "#61c05a" ul17 = "#61c05a" ul18 = "#61c05a" ul19 = "#61c05a" ul20 = "#61c05a" ul21 = "#5896de" ul22 = "#5896de" ul23 = "#5896de" ul24 = "#5896de" ul25 = "#5896de" ul26 = "#5896de" ul27 = "#5896de" ul28 = "#5896de" ul29 = "#5896de" ul30 = "#5896de" ul31 = "#a068f1" ul32 = "#a068f1" ul33 = "#a068f1" ul34 = "#a068f1" ul35 = "#a068f1" ul36 = "#a068f1" ul37 = "#a068f1" ul38 = "#a068f1" ul39 = "#a068f1" ul40 = "#a068f1" ul41 = "#ff86b2" ul42 = "#ff86b2" ul43 = "#ff86b2" ul44 = "#ff86b2" ul45 = "#ff86b2" ul46 = "#ff86b2" ul47 = "#ff86b2" ul48 = "#ff86b2" ul49 = "#ff86b2" ul50 = "#ff86b2" ul51 = "#ff9f3d" ul52 = "#ff9f3d" ul53 = "#ff9f3d" ul54 = "#ff9f3d" ul55 = "#ff9f3d" ul56 = "#ff9f3d" ul57 = "#ff9f3d" ul58 = "#ff9f3d" ul59 = "#ff9f3d" ul60 = "#ff9f3d" [fans-level] fl1 = "#61ddcb" fl2 = "#61ddcb" fl3 = "#61ddcb" fl4 = "#61ddcb" fl5 = "#5896de" fl6 = "#5896de" fl7 = "#5896de" fl8 = "#5896de" fl9 = "#a068f1" fl10 = "#a068f1" fl11 = "#a068f1" fl12 = "#a068f1" fl13 = "#ff86b2" fl14 = "#ff86b2" fl15 = "#ff86b2" fl16 = "#ff86b2" fl17 = "#f6be18" fl18 = "#f6be18" fl19 = "#f6be18" fl20 = "#f6be18" [others] vip = [ 255, 94, 144,] svip = [ 255, 208, 0,] admin = "#ea9336" default_name = "#808080" ================================================ FILE: conf/title.toml ================================================ title-176-1 = "凯旋" title-175-1 = "骑士之心" title-175-2 = "永恒誓约" title-174-1 = "幻影" title-174-2 = "光之护卫" title-173-1 = "预言家" title-172-1 = "黎明之光" title-171-1 = "蔷薇之冠" title-170-1 = "星月之梦" title-169-1 = "修仙 " title-168-1 = "舒服" title-167-1 = "rhythm saber " title-166-1 = "cantus knight" title-165-1 = "PK活动用户周榜头衔" title-164-1 = "PK主播头衔" title-163-1 = "首席应援" title-162-1 = "枸杞牛奶" title-161-1 = "审判官" title-160-1 = "天秀凉皇" title-159-1 = "王蜀黍" title-155-1 = "初号机" title-157-1 = "吃瓜群众" title-156-1 = "一本满足" title-154-1 = "为爱而生" title-153-1 = "1号玩家" title-153-2 = "荣耀之巅" title-152-1 = "大冒险家" title-151-1 = "全靠浪" title-150-1 = "甜蜜双排" title-149-1 = "大吉大利" title-148-1 = "头号歌迷" title-147-1 = "英雄联盟LPL2018助威" title-146-1 = "理事长" title-145-1 = "桃仙" title-144-1 = "一见倾心" title-144-2 = "花前月下" title-143-1 = "红线仙" title-142-1 = "喜气之王" title-141-1 = "在下福了" title-140-1 = "秋田君" title-140-2 = "年兽克星" title-139-1 = "雷狮海盗团" title-138-1 = "总选之王" title-137-1 = "一缺三" title-136-1 = "老哥稳" title-135-1 = "为所欲为" title-134-1 = "全场最佳" title-134-2 = "王者之证" title-133-1 = "一叶知秋" title-131-1 = "太阳骑士" title-131-2 = "天选之人" title-130-1 = "镜花水月" title-129-1 = "风花雪月" title-128-1 = "青葱岁月" title-128-2 = "唯望君安" title-127-1 = "自学高手" title-127-2 = "白学大师" title-126-1 = "绚烂夏花" title-126-2 = "荷塘月色" title-125-1 = "在此饶舌" title-124-1 = "大队长" title-123-1 = "一般社员" title-123-2 = "执行委员" title-122-1 = "岁月如歌" title-121-1 = "百战雄狮" title-120-1 = "门庭若市" title-119-1 = "五魁首" title-118-1 = "冒险家" title-117-1 = "圣骑士" title-116-1 = "庇护之光" title-115-1 = "终极应援" title-114-1 = "高级应援" title-113-1 = "初级应援" title-112-1 = "旅人" title-111-1 = "bilibili Link" title-110-1 = "征服王" title-109-1 = "征服者" title-108-1 = "演武者" title-108-2 = "武神" title-107-1 = "神圣" title-106-1 = "骑士" title-105-1 = "神州" title-104-1 = "蒸汽" title-103-1 = "神圣" title-102-1 = "骑士" title-101-1 = "神州" title-100-1 = "蒸汽" title-99-1 = "神谕阐释者" title-98-1 = "至高骑士" title-97-1 = "无上至尊" title-96-1 = "神曲终焉" title-95-1 = "丘比特" title-95-2 = "维纳斯" title-94-1 = "酋长" title-93-1 = "注孤身" title-92-1 = "年兽抱回家" title-91-1 = "灶神" title-90-1 = "财神爷" title-89-1 = "爆竹" title-89-2 = "意大利炮" title-88-1 = "不负初心" title-87-1 = "四季老" title-86-1 = "季老" title-85-1 = "孜孜不倦" title-84-1 = "水滴石穿" title-83-1 = "功成名就" title-82-1 = "御守" title-82-2 = "满分御守" title-82-3 = "桃花御守" title-81-1 = "新年快乐" title-80-1 = "Santa Claus" title-79-1 = "FFF团长" title-78-1 = "FFF团员" title-77-1 = "Miss·椛" title-76-1 = "理事长" title-75-1 = "见习舰长" title-75-2 = "代理提督" title-75-3 = "名誉总督" title-74-1 = "SuperStar" title-73-1 = "SuperStar" title-72-1 = "SuperStar" title-71-1 = "SuperStar" title-70-1 = "SuperStar" title-69-1 = "Star" title-68-1 = "Star" title-67-1 = "Star" title-66-1 = "Star" title-65-1 = "Star" title-64-1 = "応援" title-63-1 = "応援" title-62-1 = "応援" title-61-1 = "吃瓜群众" title-60-1 = "百鬼夜行" title-59-1 = "一本满足" title-58-1 = "盛夏花火" title-57-1 = "金闪闪" title-56-1 = "红叶祭" title-56-2 = "栖霞红枫" title-56-3 = "香山黄栌" title-56-4 = "秋之回忆" title-55-1 = "全是套路" title-54-1 = "暖心" title-53-1 = "神七" title-52-1 = "高手" title-51-1 = "大神" title-50-1 = "钻石王老五" title-49-1 = "绝对零度" title-48-1 = "钻石星尘" title-47-1 = "电视王" title-46-1 = "甘sugiru" title-45-1 = "砂糖战士" title-44-1 = "甜党" title-43-1 = "咸鱼皇" title-42-1 = "咸蛋超人" title-41-1 = "咸党" title-40-1 = "甜咸无双" title-39-1 = "七周年" title-38-1 = "超耐久" title-37-1 = "久负盛名" title-36-1 = "方得始终" title-35-1 = "关灯" title-34-1 = "起来嗨" title-33-1 = "被窝" title-32-1 = "菠菜" title-30-1 = "追云逐月" title-29-1 = "度年如日" title-28-1 = "姹紫嫣红" title-27-1 = "唱见精灵" title-26-1 = "唱见天使" title-25-1 = "唱见神话" title-24-1 = "甜心精灵" title-23-1 = "甜心天使" title-22-1 = "甜心神话" title-21-1 = "旅人" title-20-1 = "冒险家" title-19-1 = "圣骑士" title-18-1 = "庇护之光" title-17-1 = "月老" title-16-1 = "资深老司机" title-15-1 = "校长" title-14-1 = "教导主任" title-13-1 = "班主任" title-12-1 = "辅导员" title-11-1 = "雪亲王" title-10-1 = "圣尼古拉斯" title-9-1 = "真圣诞爸爸" title-8-1 = "圣诞小天使" title-7-1 = "圣诞青年" title-6-1 = "圣诞中年人" title-5-1 = "圣诞老人" title-4-1 = "超年糕团长" title-3-1 = "年糕团长" title-2-1 = "年糕团" title-1-1 = "糯米粉" ================================================ FILE: conf/title_init.py ================================================ import requests import toml rsp = requests.get('https://api.live.bilibili.com/rc/v1/Title/webTitles') rsp.encoding = 'utf-8' json_rsp = rsp.json() data = json_rsp['data'] dict_title = {i['identification']: i['name'] for i in data} with open('title.toml', 'w', encoding="utf-8") as f: toml.dump(dict_title, f) ================================================ FILE: conf/user.toml ================================================ [print_control] danmu = false debug = false [task_control] # 清理即将过期礼物,请true之后一定要把紧随其后的room设置为真实房间号 clean-expiring-gift = false # 单位秒 set-expiring-time = 43200 # 对过期礼物是否先投递到其他勋章(按照勋章等级投递),之后会剩余的清理掉roomid里面 clean_expiring_gift2all_medal = false clean-expiring-gift2room = 0 # 一天最多一个硬币兑换机会 silver2coin = false # 自动投满佩戴勋章当日亲密度 send2wearing-medal = false # 房间号 短房间 send2medal = [] # 老接口高倍率兑换硬币为银瓜子,现已失效,请勿修改!! doublegain_coin2silver = false # 输入数字 0-5 表示主站自动投币 givecoin = 0 # 投币av获取(bilitop或者uper)分别代表b站随机或者根据up主mid选取 fetchrule = "bilitop" # up主list([123]或者[123, 234, 123]等) mid = [207539637] [other_control] # 保持连接状态,下次再登陆不会重复登陆,读取存储的cookie重用,如要密码登陆,请手动清除bilibili.conf里面的cookie keep-login = true # 默认监听房间号(打印弹幕) default_monitor_roomid = 23058 # 额外自定义弹幕监控房间 raffle_minitor_roomid = 0 # raffle monitor(控制抽奖监控的,默认一个分区一个监控) area_ids = [1, 2, 3, 4, 5] ================================================ FILE: configloader.py ================================================ import toml # "#969696" def hex_to_rgb_percent(hex_str): return tuple(int(n, 16)/255 for n in (hex_str[1:3], hex_str[3:5], hex_str[5:7])) # [255 255 255] def rgb_to_percent(rgb_list): return rgb_list[0]/255, rgb_list[1]/255, rgb_list[2]/255 class ConfigLoader(): instance = None def __new__(cls, fileDir=None): if not cls.instance: cls.instance = super(ConfigLoader, cls).__new__(cls) colorfile = f'{fileDir}/conf/color.toml' userfile = f'{fileDir}/conf/user.toml' bilibilifile = f'{fileDir}/conf/bilibili.toml' titlefile = f'{fileDir}/conf/title.toml' cls.instance.colorfile = colorfile cls.instance.dic_color = cls.instance.load_color() # print(cls.instance.dic_color) cls.instance.userfile = userfile cls.instance.dic_user = cls.instance.load_user() # print(cls.instance.dic_user) cls.instance.bilibilifile = bilibilifile cls.instance.dic_bilibili = cls.instance.load_bilibili() # print(cls.instance.dic_bilibili) cls.instance.titlefile = titlefile cls.instance.dic_title = cls.instance.load_title() print("# 初始化完成") return cls.instance def write2bilibili(self, dic): with open(self.bilibilifile, encoding="utf-8") as f: dic_bilibili = toml.load(f) for i in dic.keys(): dic_bilibili['saved-session'][i] = dic[i] with open(self.bilibilifile, 'w', encoding="utf-8") as f: toml.dump(dic_bilibili, f) def load_bilibili(self): with open(self.bilibilifile, encoding="utf-8") as f: dic_bilibili = toml.load(f) if not dic_bilibili['account']['username']: username = input("# 输入帐号: ") password = input("# 输入密码: ") dic_bilibili['account']['username'] = username dic_bilibili['account']['password'] = password with open(self.bilibilifile, 'w', encoding="utf-8") as f: toml.dump(dic_bilibili, f) return dic_bilibili def load_color(self): with open(self.colorfile, encoding="utf-8") as f: dic_color = toml.load(f) for i in dic_color.values(): for j in i.keys(): if isinstance(i[j], str): i[j] = hex_to_rgb_percent(i[j]) else: i[j] = rgb_to_percent(i[j]) return dic_color def load_user(self): with open(self.userfile, encoding="utf-8") as f: dic_user = toml.load(f) return dic_user def load_title(self): with open(self.titlefile, encoding="utf-8") as f: dic_title = toml.load(f) return dic_title ================================================ FILE: connect.py ================================================ import asyncio import utils import danmu import printer from online_net import OnlineNet from configloader import ConfigLoader import random async def get_one(areaid): # 1 娱乐分区, 2 游戏分区, 3 手游分区, 4 绘画分区 if areaid == 1: roomid = 23058 if (await utils.check_room_for_danmu(roomid, areaid)): printer.info([f'{areaid}号弹幕监控选择房间({roomid})'], True) return roomid while True: json_rsp = await OnlineNet().req('req_realroomid', areaid) data = json_rsp['data'] if not data: await asyncio.sleep(3) printer.warn(json_rsp) continue roomid = random.choice(data)['roomid'] if (await utils.check_room_for_danmu(roomid, areaid)): printer.info([f'{areaid}号弹幕监控选择房间({roomid})'], True) return roomid class connect(): __slots__ = ('danmuji', 'room_id', 'area_id') instance = None def __new__(cls, *args, **kw): if not cls.instance: cls.instance = super(connect, cls).__new__(cls, *args, **kw) cls.instance.danmuji = None cls.instance.room_id = 0 cls.instance.area_id = -1 return cls.instance async def run(self): self.room_id = ConfigLoader().dic_user['other_control']['default_monitor_roomid'] self.danmuji = danmu.DanmuPrinter(self.room_id, self.area_id) time_now = 0 while True: if int(utils.CurrentTime()) - time_now <= 3: printer.info(['当前网络不稳定,弹幕监控将自动延迟3秒后重启'], True) await asyncio.sleep(3) printer.info(['正在启动直播监控弹幕姬'], True) time_now = int(utils.CurrentTime()) connect_results = await self.danmuji.open() if not connect_results: continue task_main = asyncio.ensure_future(self.danmuji.read_datas()) task_heartbeat = asyncio.ensure_future(self.danmuji.heart_beat()) tasks = [task_main, task_heartbeat] finished, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED) printer.info(['主弹幕姬异常或主动断开,正在处理剩余信息'], True) if not task_heartbeat.done(): task_heartbeat.cancel() await self.danmuji.close() await asyncio.wait(pending) printer.info(['主弹幕姬退出,剩余任务处理完毕'], True) @staticmethod async def reconnect(roomid): ConfigLoader().dic_user['other_control']['default_monitor_roomid'] = roomid print('已经切换roomid') if connect.instance.danmuji is not None: connect.instance.danmuji.room_id = roomid await connect.instance.danmuji.close() class RaffleConnect(): def __init__(self, areaid): self.danmuji = None self.roomid = 0 self.areaid = areaid async def run(self): self.danmuji = danmu.DanmuRaffleHandler(self.roomid, self.areaid) time_now = 0 while True: if int(utils.CurrentTime()) - time_now <= 3: printer.info(['当前网络不稳定,弹幕监控将自动延迟3秒后重启'], True) await asyncio.sleep(3) self.danmuji.room_id = await get_one(self.areaid) printer.info(['正在启动抽奖监控弹幕姬'], True) time_now = int(utils.CurrentTime()) connect_results = await self.danmuji.open() if not connect_results: continue task_main = asyncio.ensure_future(self.danmuji.read_datas()) task_heartbeat = asyncio.ensure_future(self.danmuji.heart_beat()) task_checkarea = asyncio.ensure_future(self.danmuji.check_area()) tasks = [task_main, task_heartbeat, task_checkarea] finished, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED) printer.info([f'{self.areaid}号弹幕姬异常或主动断开,正在处理剩余信息'], True) if not task_heartbeat.done(): task_heartbeat.cancel() if not task_checkarea.done(): task_checkarea.cancel() await self.danmuji.close() await asyncio.wait(pending) printer.info([f'{self.areaid}号弹幕姬退出,剩余任务处理完毕'], True) class YjConnection(): def __init__(self): self.danmuji = None self.roomid = 0 self.areaid = 0 async def run(self): self.roomid = ConfigLoader().dic_user['other_control']['raffle_minitor_roomid'] if not self.roomid: return self.danmuji = danmu.YjMonitorHandler(self.roomid, self.areaid) time_now = 0 while True: if int(utils.CurrentTime()) - time_now <= 3: printer.info(['当前网络不稳定,弹幕监控将自动延迟3秒后重启'], True) await asyncio.sleep(3) printer.info(['正在启动Yj监控弹幕姬'], True) time_now = int(utils.CurrentTime()) connect_results = await self.danmuji.open() if not connect_results: continue task_main = asyncio.ensure_future(self.danmuji.read_datas()) task_heartbeat = asyncio.ensure_future(self.danmuji.heart_beat()) tasks = [task_main, task_heartbeat] finished, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED) printer.info(['Yj弹幕姬异常或主动断开,正在处理剩余信息'], True) if not task_heartbeat.done(): task_heartbeat.cancel() await self.danmuji.close() await asyncio.wait(pending) printer.info(['Yj弹幕姬退出,剩余任务处理完毕'], True) ================================================ FILE: danmu.py ================================================ from statistics import Statistics import printer import rafflehandler import utils import asyncio import struct import json import sys import aiohttp class BaseDanmu(): structer = struct.Struct('!I2H2I') def __init__(self, room_id, area_id): self.client = aiohttp.ClientSession() self._area_id = area_id self.room_id = room_id self._bytes_heartbeat = self._wrap_str(opt=2, body='') @property def room_id(self): # 仅仅为了借用roomi_id.setter,故不设置 pass @room_id.setter def room_id(self, room_id): self._room_id = room_id str_conn_room = f'{{"uid":0,"roomid":{room_id},"protover":1,"platform":"web","clientver":"1.3.3"}}' self._bytes_conn_room = self._wrap_str(opt=7, body=str_conn_room) def _wrap_str(self, opt, body, len_header=16, ver=1, seq=1): remain_data = body.encode('utf-8') len_data = len(remain_data) + len_header header = self.structer.pack(len_data, len_header, ver, opt, seq) data = header + remain_data return data async def _send_bytes(self, bytes_data): try: await self.ws.send_bytes(bytes_data) except asyncio.CancelledError: return False except: print(sys.exc_info()[0], sys.exc_info()[1]) return False return True async def _read_bytes(self): bytes_data = None try: # 如果调用aiohttp的bytes read,none的时候,会raise exception msg = await asyncio.wait_for(self.ws.receive(), timeout=35.0) bytes_data = msg.data except asyncio.TimeoutError: print('# 由于心跳包30s一次,但是发现35内没有收到任何包,说明已经悄悄失联了,主动断开') return None except: print(sys.exc_info()[0], sys.exc_info()[1]) print('请联系开发者') return None return bytes_data async def open(self): try: url = 'wss://broadcastlv.chat.bilibili.com:443/sub' self.ws = await asyncio.wait_for(self.client.ws_connect(url), timeout=3) except: print("# 连接无法建立,请检查本地网络状况") print(sys.exc_info()[0], sys.exc_info()[1]) return False printer.info([f'{self._area_id}号弹幕监控已连接b站服务器'], True) return (await self._send_bytes(self._bytes_conn_room)) async def heart_beat(self): try: while True: if not (await self._send_bytes(self._bytes_heartbeat)): return await asyncio.sleep(30) except asyncio.CancelledError: pass async def read_datas(self): while True: datas = await self._read_bytes() # 本函数对bytes进行相关操作,不特别声明,均为bytes if datas is None: return data_l = 0 len_datas = len(datas) while data_l != len_datas: # 每片data都分为header和body,data和data可能粘连 # data_l == header_l && next_data_l = next_header_l # ||header_l...header_r|body_l...body_r||next_data_l... tuple_header = self.structer.unpack_from(datas[data_l:]) len_data, len_header, ver, opt, seq = tuple_header body_l = data_l + len_header next_data_l = data_l + len_data body = datas[body_l:next_data_l] # 人气值(或者在线人数或者类似)以及心跳 if opt == 3: # UserCount, = struct.unpack('!I', remain_data) printer.debug(f'弹幕心跳检测{self._area_id}') # cmd elif opt == 5: if not self.handle_danmu(body): return # 握手确认 elif opt == 8: printer.info([f'{self._area_id}号弹幕监控进入房间({self._room_id})'], True) else: printer.warn(datas[data_l:next_data_l]) data_l = next_data_l # 待确认 async def close(self): try: await self.ws.close() except: print('请联系开发者', sys.exc_info()[0], sys.exc_info()[1]) if not self.ws.closed: printer.info([f'请联系开发者 {self._area_id}号弹幕收尾模块状态{self.ws.closed}'], True) def handle_danmu(self, body): return True class DanmuPrinter(BaseDanmu): def handle_danmu(self, body): dic = json.loads(body.decode('utf-8')) cmd = dic['cmd'] # print(cmd) if cmd == 'DANMU_MSG': # print(dic) printer.print_danmu(dic) return True class DanmuRaffleHandler(BaseDanmu): async def check_area(self): try: while True: is_ok = await asyncio.shield(utils.check_room_for_danmu(self._room_id, self._area_id)) if not is_ok: printer.info([f'{self._room_id}不再适合作为监控房间,即将切换'], True) return await asyncio.sleep(300) except asyncio.CancelledError: pass def handle_danmu(self, body): dic = json.loads(body.decode('utf-8')) cmd = dic['cmd'] if cmd == 'PREPARING': printer.info([f'{self._area_id}号弹幕监控房间下播({self._room_id})'], True) 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的) # 8 全区广播:主播<%红莉栖魔王喵%>开启了“任意门”,点击前往TA的房间去抽奖吧! msg_type = dic['msg_type'] msg_common = dic['msg_common'] real_roomid = dic['real_roomid'] msg_common = dic['msg_common'].replace(' ', '') msg_common = msg_common.replace('”', '') msg_common = msg_common.replace('“', '') if msg_type == 2 or msg_type == 8: str_gift = msg_common.split('%>')[-1].split(',')[0] if '个' in str_gift: raffle_num, raffle_name = str_gift.split('个') elif '了' in str_gift: raffle_num = 1 raffle_name = str_gift.split('了')[-1] else: raffle_num = 1 raffle_name = str_gift broadcast = msg_common.split('广播')[0] printer.info([f'{self._area_id}号弹幕监控检测到{real_roomid:^9}的{raffle_name}'], True) rafflehandler.Rafflehandler.Put2Queue((real_roomid,), rafflehandler.handle_1_room_TV) broadcast_type = 0 if broadcast == '全区' else 1 Statistics.add2pushed_raffle(raffle_name, broadcast_type) elif msg_type == 3: raffle_name = msg_common.split('开通了')[-1][:2] printer.info([f'{self._area_id}号弹幕监控检测到{real_roomid:^9}的{raffle_name}'], True) rafflehandler.Rafflehandler.Put2Queue((real_roomid,), rafflehandler.handle_1_room_guard) broadcast_type = 0 if raffle_name == '总督' else 2 Statistics.add2pushed_raffle(raffle_name, broadcast_type) elif msg_type == 6: raffle_name = '二十倍节奏风暴' printer.info([f'{self._area_id}号弹幕监控检测到{real_roomid:^9}的{raffle_name}'], True) rafflehandler.Rafflehandler.Put2Queue((real_roomid,), rafflehandler.handle_1_room_storm) Statistics.add2pushed_raffle(raffle_name) return True class YjMonitorHandler(BaseDanmu): def __init__(self, room_id, area_id): super().__init__(room_id, area_id) keys = '阝飠牜饣卩卪厸厶厽孓宀巛巜彳廴彡彐忄扌攵氵灬爫犭疒癶礻糹纟罒罓耂虍訁覀兦亼亽亖亗吂卝匸皕旡玊尐幵朩囘囙囜囝囟囡団囤囥囦囧囨囩囪囫囬囮囯困囱囲図囵囶囷囸囹固囻囼图囿圀圁圂圃圄圅圆圇圉圊圌圍圎圏圐圑園圓圔圕圖圗團圙圚圛圜圝圞' self.__reverse_keys = {value: i for i, value in enumerate(keys)} self.__read = {} def __base2dec(self, str_num, base=110): result = 0 for i in str_num: result = result * base + self.__reverse_keys[i] return result def __reverse(self, msg): msg = msg.replace('?', '') first = self.__reverse_keys.get(msg[0], -1) last = self.__reverse_keys.get(msg[-1], -1) # 校验 if 0 <= first <= 109 and 0 <= last <= 109 and not (first + last - 109): type = msg[-2] msg_id, id = map(self.__base2dec, msg[:-2].split('.')) return msg_id, type, id return None def __combine_piece(self, uid, msg): # None/'' if not msg: return None if uid not in self.__read: self.__read[uid] = {} user_danmus = self.__read[uid] msg_id, type, id = msg msg_id_wanted = (msg_id - 1) if (msg_id % 2) else (msg_id + 1) id_wanted = user_danmus.pop(msg_id_wanted, None) if id_wanted is not None: if msg_id % 2: return type, id_wanted, id else: return type, id, id_wanted else: user_danmus[msg_id] = id return None def handle_danmu(self, body): dic = json.loads(body.decode('utf-8')) cmd = dic['cmd'] # print(cmd) if cmd == 'DANMU_MSG': info = dic['info'] ori = info[1] uid = info[2][0] # print(ori) try: msg = self.__reverse(ori) ''' if msg is not None: msg_id, type, id = msg if type == '~' and not msg_id % 2: storm_id = id print('节奏风暴', storm_id) rafflehandler.Rafflehandler.Put2Queue((storm_id,), rafflehandler.handle_1_storm_raffle) ''' result = self.__combine_piece(uid, msg) # print('监控read dic', self.__read) if result is None: return True # print(result) type, raffle_id, room_id = result if type == '+': printer.info([f'{self._area_id}号弹幕监控检测到{room_id:^9}的大航海(id: {raffle_id})'], True) rafflehandler.Rafflehandler.Put2Queue((room_id, raffle_id), rafflehandler.handle_1_room_guard) Statistics.add2pushed_raffle('Yj协同大航海', 2) except Exception: printer.warn(f'Yj监控房间内可能有恶意干扰{uid}: {ori}') return True ================================================ FILE: online_net.py ================================================ from bilibili import bilibili from configloader import ConfigLoader import rsa import base64 from urllib import parse import printer import asyncio def calc_name_passw(key, Hash, username, password): pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(key.encode()) password = base64.b64encode(rsa.encrypt((Hash + password).encode('utf-8'), pubkey)) password = parse.quote_plus(password) username = parse.quote_plus(username) return username, password def LoginWithPwd(): username = ConfigLoader().dic_bilibili['account']['username'] password = ConfigLoader().dic_bilibili['account']['password'] response = bilibili.request_getkey() value = response.json()['data'] key = value['key'] Hash = str(value['hash']) username, password = calc_name_passw(key, Hash, username, password) captcha = None response = bilibili.normal_login(username, password, captcha) while response.json()['code'] == -105: captcha = bilibili.get_captcha(username, password) response = bilibili.normal_login(username, password, captcha) json_rsp = response.json() # print(json_rsp) if not json_rsp['code'] and not json_rsp['data']['status']: data = json_rsp['data'] access_key = data['token_info']['access_token'] refresh_token = data['token_info']['refresh_token'] cookie = data['cookie_info']['cookies'] generator_cookie = (f'{i["name"]}={i["value"]}' for i in cookie) cookie_format = ';'.join(generator_cookie) dic_saved_session = { 'csrf': cookie[0]['value'], 'access_key': access_key, 'refresh_token': refresh_token, 'cookie': cookie_format, 'uid': cookie[1]['value'] } # print(dic_saved_session) bilibili.load_session(dic_saved_session) if ConfigLoader().dic_user['other_control']['keep-login']: ConfigLoader().write2bilibili(dic_saved_session) printer.info(['登陆成功'], True) return True else: printer.info([f'登录失败,错误信息为:{json_rsp}'], True) return False def login(): if ConfigLoader().dic_bilibili['saved-session']['cookie']: bilibili.load_session(ConfigLoader().dic_bilibili['saved-session']) return HandleExpire() else: return LoginWithPwd() def logout(): response = bilibili.request_logout() if response.json()['code']: print('登出失败', response) else: print('成功退出登陆') def check_token(): response = bilibili.request_check_token() json_response = response.json() if not json_response['code'] and 'mid' in json_response['data']: print('token有效期检查: 仍有效') # print(json_response) return True print('token可能过期', json_response) return False def RefreshToken(): # return response = bilibili.request_refresh_token() json_response = response.json() # print(json_response) if not json_response['code'] and 'mid' in json_response['data']['token_info']: print('token刷新成功') data = json_response['data'] access_key = data['token_info']['access_token'] refresh_token = data['token_info']['refresh_token'] cookie = data['cookie_info']['cookies'] generator_cookie = (f'{i["name"]}={i["value"]}' for i in cookie) cookie_format = ';'.join(generator_cookie) dic_saved_session = { 'csrf': cookie[0]['value'], 'access_key': access_key, 'refresh_token': refresh_token, 'cookie': cookie_format } bilibili.load_session(dic_saved_session) if ConfigLoader().dic_user['other_control']['keep-login']: ConfigLoader().write2bilibili(dic_saved_session) # 更新token信息 return True print('联系作者(token刷新失败,cookie过期)', json_response) return False def HandleExpire(): if not check_token(): if not RefreshToken(): return LoginWithPwd() else: if not check_token(): print('请联系作者!!!!!!!!!') return LoginWithPwd() return True class OnlineNet(): instance = None def __new__(cls, *args, **kw): if not cls.instance: cls.instance = super(OnlineNet, cls).__new__(cls, *args, **kw) cls.instance.bili = bilibili() cls.instance.var_is_online = True cls.instance.list_delay = [] return cls.instance @property def is_online(self): return self.var_is_online @is_online.setter def is_online(self, setting): self.var_is_online = setting if setting: for future in self.list_delay: future.set_result(True) del self.list_delay[:] async def req(self, str_func, *args): while True: rsp = await getattr(self.bili, str_func)(*args) is_online = self.is_online # print(rsp) if not is_online: future = asyncio.Future() self.list_delay.append(future) await future # 未登陆且未处理 if rsp == 3 and is_online: printer.info([f'判定出现了登陆失败,且未处理'], True) self.is_online = False # login HandleExpire() # await asyncio.sleep(10) print(self.list_delay) printer.info([f'已经登陆了'], True) self.is_online = True # rsp = await getattr(self.bili, str_func)(*args) # 未登陆,但已处理 elif not is_online: printer.info([f'判定出现了登陆失败,已经处理'], True) # rsp = await getattr(self.bili, str_func)(*args) else: return rsp ================================================ FILE: printer.py ================================================ import sys import time from configloader import ConfigLoader if sys.platform == 'ios': import console class BasePrinter(): def init_config(self): configs = ConfigLoader() self.dic_color = configs.dic_color self.dic_user = configs.dic_user self.dic_title = configs.dic_title self.danmu_control = self.dic_user['print_control']['danmu'] def control_printer(self, danmu_control=None, debug_control=None): if danmu_control is not None: self.danmu_control = danmu_control ConfigLoader().dic_user['print_control']['danmu'] = danmu_control if debug_control is not None: ConfigLoader().dic_user['print_control']['debug'] = debug_control self.debug_control = debug_control def timestamp(self): str_time = time.strftime("[%Y-%m-%d %H:%M:%S] ", time.localtime()) return str_time def info(self, list_msg, tag_time=False): if tag_time: print(self.timestamp(), end='') for msg in list_msg: print(msg) def warn(self, msg): print(msg, file=sys.stderr) with open('bili.log', 'a', encoding='utf-8') as f: f.write(f'{self.timestamp()}{msg}\n') def debug(self, msg): if ConfigLoader().dic_user['print_control']['debug']: self.warn(msg) def error(self, msg): self.warn(msg) sys.exit(-1) class PythonistaPrinter(BasePrinter): # "#969696" def hex_to_rgb_percent(self, hex_str): return tuple(int(n, 16)/255 for n in (hex_str[1:3], hex_str[3:5], hex_str[5:7])) # 弹幕 礼物 。。。。type def print_danmu(self, dic_msg, type='normal'): if not self.danmu_control: return info = dic_msg['info'] list_msg = [] list_color = [] if info[7] == 3: # print('舰', end=' ') list_msg.append('⚓️ ') list_color.append([]) else: if info[2][3] == 1: if info[2][4] == 0: list_msg.append('爷 ') list_color.append(self.dic_color['others']['vip']) else: list_msg.append('爷 ') list_color.append(self.dic_color['others']['svip']) if info[2][2] == 1: list_msg.append('房管 ') list_color.append(self.dic_color['others']['admin']) # 勋章 if info[3]: list_color.append(self.dic_color['fans-level'][f'fl{info[3][0]}']) list_msg.append(f'{info[3][1]}|{info[3][0]} ') # 等级 if not info[5]: list_color.append(self.dic_color['user-level'][f'ul{info[4][0]}']) list_msg.append(f'UL{info[4][0]} ') try: if info[2][7]: list_color.append(self.hex_to_rgb_percent(info[2][7])) list_msg.append(info[2][1] + ':') else: list_msg.append(info[2][1] + ':') list_color.append(self.dic_color['others']['default_name']) except: print("# 小电视降临本直播间") list_msg.append(info[2][1] + ':') list_color.append(self.dic_color['others']['default_name']) list_msg.append(info[1]) list_color.append([]) for i, j in zip(list_msg, list_color): console.set_color(*j) print(i, end='') print() console.set_color() class NormalPrinter(BasePrinter): def print_danmu(self, dic_msg, type='normal'): if not self.danmu_control: return info = dic_msg['info'] list_msg = [] if info[7] == 3: # print('舰', end=' ') list_msg.append('⚓️ ') else: if info[2][3] == 1: if info[2][4] == 0: list_msg.append('爷 ') else: list_msg.append('爷 ') if info[2][2] == 1: list_msg.append('房管 ') # 勋章 if info[3]: list_msg.append(f'{info[3][1]}|{info[3][0]} ') # 等级 if not info[5]: list_msg.append(f'UL{info[4][0]} ') try: if info[2][7]: list_msg.append(info[2][1] + ':') else: list_msg.append(info[2][1] + ':') except: print("# 小电视降临本直播间") list_msg.append(info[2][1] + ':') list_msg.append(info[1]) print(''.join(list_msg)) if (sys.platform == 'ios'): printer = PythonistaPrinter() else: printer = NormalPrinter() def init_config(): printer.init_config() def info(list_msg, tag_time=False): printer.info(list_msg, tag_time) def warn(msg): printer.warn(msg) def error(msg): printer.error(msg) def debug(msg): printer.debug(msg) def print_danmu(dic_msg, type='normal'): printer.print_danmu(dic_msg, type) def control_printer(danmu_control=None, debug_control=None): printer.control_printer(danmu_control, debug_control) ================================================ FILE: rafflehandler.py ================================================ from online_net import OnlineNet from statistics import Statistics import printer import utils import asyncio import time import random from bilitimer import BiliTimer def CurrentTime(): currenttime = int(time.time()) return currenttime class Rafflehandler: __slots__ = ('queue_raffle', 'list_raffle_id') instance = None def __new__(cls, *args, **kw): if not cls.instance: cls.instance = super(Rafflehandler, cls).__new__(cls, *args, **kw) cls.instance.queue_raffle = asyncio.Queue() cls.instance.list_raffle_id = [] return cls.instance async def run(self): while True: raffle = await self.queue_raffle.get() await asyncio.sleep(0.5) list_raffle0 = [self.queue_raffle.get_nowait() for i in range(self.queue_raffle.qsize())] list_raffle0.append(raffle) list_raffle = list(set(list_raffle0)) # print('过滤完毕') # if len(list_raffle) != len(list_raffle0): # print('过滤机制起作用') tasklist = [] for i in list_raffle: i = list(i) i[0] = list(i[0]) for j in range(len(i[0])): if isinstance(i[0][j], tuple): # print('检测') # i[0] = list(i[0]) i[0][j] = await i[0][j][1](*(i[0][j][0])) # print(i) task = asyncio.ensure_future(i[1](*i[0])) tasklist.append(task) # await asyncio.wait(tasklist, return_when=asyncio.ALL_COMPLETED) @staticmethod def Put2Queue(value, func): # print('welcome to appending') Rafflehandler.instance.queue_raffle.put_nowait((value, func)) # print('appended') return @staticmethod async def Put2Queue_wait(value, func): # print('welcome to appending') await Rafflehandler.instance.queue_raffle.put((value, func)) # print('appended') return @staticmethod def getlist(): print('目前TV任务队列状况', Rafflehandler.instance.queue_raffle.qsize()) def add2raffle_id(self, raffle_id): self.list_raffle_id.append(raffle_id) if len(self.list_raffle_id) > 150: # print(self.list_raffle_id) del self.list_raffle_id[:75] # print(self.list_raffle_id) def check_duplicate(self, raffle_id): return (raffle_id in self.list_raffle_id) async def handle_1_TV_raffle(num, real_roomid, raffleid, raffle_type): while True: json_response2 = await OnlineNet().req('get_gift_of_TV_app', real_roomid, raffleid, raffle_type) code = json_response2['code'] if not code: break elif code == -403: return True elif code == -405: print('没抢到。。。。。') printer.warn(f'{raffleid} {raffle_type} {num}') return False elif code == 400: print(json_response2) return tasklist = [] for i in range(60): task = asyncio.ensure_future(handle_1_TV_raffle_black(num, real_roomid, raffleid, raffle_type)) tasklist.append(task) await asyncio.wait(tasklist, return_when=asyncio.FIRST_COMPLETED) return elif code != -401 and code != -403: pass print('如果循环请联系作者', num, real_roomid, raffleid, raffle_type) data = json_response2['data'] Statistics.append_to_TVlist(raffleid, real_roomid) Statistics.add_to_result(data['gift_name'], int(data['gift_num'])) printer.info([f'参与了房间{real_roomid:^9}的道具抽奖'], True) # printer.info([f'# 道具抽奖状态: {json_response2["msg"]}']) printer.info([f'# 房间{real_roomid:^9}网页端活动抽奖结果: {data["gift_name"]}X{data["gift_num"]}']) return True async def handle_1_guard_raffle(num, roomid, raffleid): await asyncio.sleep(random.uniform(0.5, min(30, num * 1.3))) json_response2 = await OnlineNet().req('get_gift_of_guard', roomid, raffleid) # print(json_response2) if not json_response2['code']: print("# 获取到房间 %s 的提督/舰长奖励: " % (roomid), json_response2['data']['message']) # print(json_response2) Statistics.append_to_guardlist() else: print(json_response2) return True async def handle_1_storm_raffle(id): json_response1 = await OnlineNet().req('get_gift_of_storm', id) print(json_response1) async def handle_1_activity_raffle(num, text1, raffleid): # print('参与') # await asyncio.sleep(random.uniform(0.5, min(30, num * 1.3))) json_response1 = await OnlineNet().req('get_gift_of_events_app', text1, raffleid) # json_pc_response = await OnlineNet().req('get_gift_of_events_web', text1, text2, raffleid) # print(json_response1) printer.info([f'参与了房间{text1:^9}的活动抽奖'], True) if not json_response1['code']: printer.info([f'# 移动端活动抽奖结果: {json_response1["data"]["gift_desc"]}']) Statistics.add_to_result(*(json_response1['data']['gift_desc'].split('X'))) elif json_response1['code'] == 400: print(json_response1) return tasklist = [] for i in range(60): task = asyncio.ensure_future(handle_1_activity_raffle_black(num, text1, raffleid)) tasklist.append(task) await asyncio.wait(tasklist, return_when=asyncio.FIRST_COMPLETED) return # print(json_response1) else: printer.info([f'# 移动端活动抽奖结果: {json_response1}']) # printer.info( # [f'# 网页端活动抽奖状态: {json_pc_response}']) # if not json_pc_response['code']: # Statistics.append_to_activitylist(raffleid, text1) # else: # print(json_pc_response) return True async def handle_1_room_TV(real_roomid): result = await utils.enter_room(real_roomid) if result: json_response = await OnlineNet().req('get_giftlist_of_TV', real_roomid) current_time = CurrentTime() # print(json_response['data']['list']) checklen = json_response['data']['list'] list_available_raffleid = [] for j in checklen: raffle_id = j['raffleId'] raffle_type = j['type'] time_wanted = j['time_wait'] + current_time # 处理一些重复 if not Rafflehandler().check_duplicate(raffle_id): print(raffle_id) list_available_raffleid.append((raffle_id, raffle_type, time_wanted)) Rafflehandler().add2raffle_id(raffle_id) num_available = len(list_available_raffleid) # print(list_available_raffleid) for raffle_id, raffle_type, time_wanted in list_available_raffleid: BiliTimer.append2list_jobs(handle_1_TV_raffle, time_wanted, (num_available, real_roomid, raffle_id, raffle_type)) async def handle_1_room_storm(roomid): result = await utils.enter_room(roomid) if result: temp = await OnlineNet().req('get_giftlist_of_storm', roomid) check = len(temp['data']) list_available_raffleid = [] if check != 0 and temp['data']['hasJoin'] != 1: id = temp['data']['id'] list_available_raffleid.append((id, 0)) for id, time_wanted in list_available_raffleid: BiliTimer.append2list_jobs(handle_1_storm_raffle, time_wanted, (id,)) async def handle_1_room_activity(text1): result = await utils.enter_room(text1) if result: json_response = await OnlineNet().req('get_giftlist_of_events', text1) # print(json_response) checklen = json_response['data']['lotteryInfo'] list_available_raffleid = [] for j in checklen: # await asyncio.sleep(random.uniform(0.5, 1)) # resttime = j['time'] raffleid = j['eventType'] # if Statistics.check_activitylist(text1, raffleid): list_available_raffleid.append(raffleid) tasklist = [] num_available = len(list_available_raffleid) # print(list_available_raffleid) for raffleid in list_available_raffleid: task = asyncio.ensure_future(handle_1_activity_raffle(num_available, text1, raffleid)) tasklist.append(task) if tasklist: raffle_results = await asyncio.gather(*tasklist) if False in raffle_results: print('有繁忙提示,稍后重新尝试') Rafflehandler.Put2Queue((text1), handle_1_room_activity) async def handle_1_room_guard(roomid, raffleid=None): result = await utils.enter_room(roomid) if result: if raffleid is not None: json_response1 = {'data': [{'id': raffleid}]} else: for i in range(10): json_response1 = await OnlineNet().req('get_giftlist_of_guard', roomid) # print(json_response1) if not json_response1['data']: await asyncio.sleep(1) else: break if not json_response1['data']: print(f'{roomid}没有guard或者guard已经领取') return list_available_raffleid = [] # guard这里领取后,list对应会消失,其实就没有status了,这里是为了统一 for j in json_response1['data']: raffle_id = j['id'] if not Rafflehandler().check_duplicate(raffle_id): # print(raffle_id) list_available_raffleid.append(raffle_id) Rafflehandler().add2raffle_id(raffle_id) tasklist = [] num_available = len(list_available_raffleid) for raffleid in list_available_raffleid: task = asyncio.ensure_future(handle_1_guard_raffle(num_available, roomid, raffleid)) tasklist.append(task) if tasklist: raffle_results = await asyncio.gather(*tasklist) if False in raffle_results: print('有繁忙提示,稍后重新尝试') Rafflehandler.Put2Queue((roomid,), handle_1_room_guard) async def handle_1_TV_raffle_black(num, real_roomid, raffleid, raffle_type): # print('ffffffffffggggdgdfddf') for i in range(50): json_response2 = await OnlineNet().req('get_gift_of_TV_app', real_roomid, raffleid, raffle_type) code = json_response2['code'] if not code: break elif code == -403: return True elif code == -405: print('没抢到。。。。。') printer.warn(raffleid) return False elif code != -401 and code != -403: # print('00', json_response2) pass # await asyncio.sleep() code = json_response2['code'] if code: await asyncio.sleep(5) return data = json_response2['data'] Statistics.append_to_TVlist(raffleid, real_roomid) Statistics.add_to_result(data['gift_name'], int(data['gift_num'])) printer.info([f'参与了房间{real_roomid:^9}的道具抽奖'], True) # printer.info([f'# 道具抽奖状态: {json_response2["msg"]}']) printer.info([f'# 房间{real_roomid:^9}网页端活动抽奖结果: {data["gift_name"]}X{data["gift_num"]}']) return True async def handle_1_activity_raffle_black(num, text1, raffleid): # print('参与') # await asyncio.sleep(random.uniform(0.5, min(30, num * 1.3))) for i in range(50): json_response1 = await OnlineNet().req('get_gift_of_events_app', text1, raffleid) code = json_response1['code'] if not code: break elif code == -403: return True elif code == -405: print('没抢到。。。。。') printer.warn(raffleid) return False elif code != -401 and code != -403: # print('00', json_response2) pass # json_pc_response = await OnlineNet().req('get_gift_of_events_web', text1, text2, raffleid) # print(json_response1) printer.info([f'参与了房间{text1:^9}的活动抽奖'], True) if not json_response1['code']: printer.info([f'# 移动端活动抽奖结果: {json_response1["data"]["gift_desc"]}']) Statistics.add_to_result(*(json_response1['data']['gift_desc'].split('X'))) else: # print(json_response1) printer.info([f'# 移动端活动抽奖结果: {json_response1}']) return True ================================================ FILE: requirements.txt ================================================ requests rsa aiohttp # Pillow 当你需要自己输入验证码的时候请安装 toml ================================================ FILE: run.py ================================================ import OnlineHeart import Silver import Tasks import connect from rafflehandler import Rafflehandler import asyncio import printer from statistics import Statistics from bilibili import bilibili from configloader import ConfigLoader import threading import os import online_net import bili_console from bilitimer import BiliTimer loop = asyncio.get_event_loop() fileDir = os.path.dirname(os.path.realpath(__file__)) conf = ConfigLoader(fileDir) area_ids = conf.dic_user['other_control']['area_ids'] # print('Hello world.') printer.init_config() bilibili() online_net.login() online_net.OnlineNet() Statistics(len(area_ids)) rafflehandler = Rafflehandler() var_console = bili_console.Biliconsole(loop) list_raffle_connection = [connect.RaffleConnect(i) for i in area_ids] list_raffle_connection_task = [i.run() for i in list_raffle_connection] yjconnection = connect.YjConnection() danmu_connection = connect.connect() bili_timer = BiliTimer(loop) console_thread = threading.Thread(target=var_console.cmdloop) console_thread.start() Tasks.init() tasks = [ OnlineHeart.run(), Silver.run(), danmu_connection.run(), rafflehandler.run(), yjconnection.run() ] try: loop.run_until_complete(asyncio.wait(tasks + list_raffle_connection_task)) except KeyboardInterrupt: # print(sys.exc_info()[0], sys.exc_info()[1]) if ConfigLoader().dic_user['other_control']['keep-login']: pass else: response = online_net.logout() console_thread.join() loop.close() ================================================ FILE: statistics.py ================================================ class Statistics: instance = None def __new__(cls, area_num=0): if not cls.instance: cls.instance = super(Statistics, cls).__new__(cls) cls.instance.area_num = area_num cls.instance.activity_id_list = [] # cls.instance.activity_time_list = [] cls.instance.TV_id_list = [] # cls.instance.TV_time_list = [] cls.instance.pushed_raffle = {} cls.instance.joined_raffle = {} cls.instance.result = {} # cls.instance.TVsleeptime = 185 # cls.instance.activitysleeptime = 125 return cls.instance @staticmethod def add_to_result(type, num): inst = Statistics.instance inst.result[type] = inst.result.get(type, 0) + int(num) @staticmethod def getlist(): inst = Statistics.instance print('本次推送抽奖统计:') for k, v in inst.pushed_raffle.items(): if isinstance(v, int): print(f'{v:^5} X {k}') else: print(f'{v:^5.2f} X {k}') print() print('本次参与抽奖统计:') for k, v in inst.joined_raffle.items(): print(f'{v:^5} X {k}') print() print('本次抽奖结果统计:') for k, v in inst.result.items(): print(f'{v:^5} X {k}') @staticmethod def append_to_activitylist(raffleid, text1, time=''): inst = Statistics.instance inst.activity_id_list.append((text1, raffleid)) # inst.activity_time_list.append(int(time)) # inst.activity_time_list.append(int(CurrentTime())) inst.append2joined_raffle('活动(合计)') # print("activity加入成功", inst.joined_event) @staticmethod def append_to_TVlist(raffleid, real_roomid, time=''): inst = Statistics.instance inst.TV_id_list.append((real_roomid, raffleid)) # inst.TV_time_list.append(int(time)+int(CurrentTime())) # inst.TV_time_list.append(int(CurrentTime())) inst.append2joined_raffle('小电视(合计)') # print("tv加入成功", inst.joined_TV) @staticmethod def append_to_guardlist(): inst = Statistics.instance inst.append2joined_raffle('大航海(合计)') @staticmethod def append2joined_raffle(type, num=1): inst = Statistics.instance inst.joined_raffle[type] = inst.joined_raffle.get(type, 0) + int(num) @staticmethod def add2pushed_raffle(raffle_name, broadcast_type=0, num=1): # broadcast_type 0全区 1分区 2本房间 inst = Statistics.instance if broadcast_type == 0: inst.pushed_raffle[raffle_name] = inst.pushed_raffle.get(raffle_name, 0) + int(num) / inst.area_num else: inst.pushed_raffle[raffle_name] = inst.pushed_raffle.get(raffle_name, 0) + int(num) @staticmethod def check_TVlist(real_roomid, raffleid): inst = Statistics.instance if (real_roomid, raffleid) not in inst.TV_id_list: return True return False @staticmethod def check_activitylist(real_roomid, raffleid): inst = Statistics.instance if (real_roomid, raffleid) not in inst.activity_id_list: return True return False @staticmethod def checklist(): print('目前activity任务队列状况:', Statistics.instance.activity_id_list) print('TV:', Statistics.instance.TV_id_list) ================================================ FILE: ugly_auto_reboot.py ================================================ import subprocess import time import sys TIME = 3600 CMD = "run.py" class Auto_Run(): def __init__(self, sleep_time, cmd): self.sleep_time = sleep_time self.cmd = cmd self.ext = (cmd[-3:]).lower() self.p = None self.run() try: while 1: time.sleep(sleep_time * 20) self.poll = self.p.poll() if self.p.poll() is None: print("restarting......") self.p.kill() self.run() else: print("starting......") self.run() except KeyboardInterrupt as e: print("exit???") def run(self): if self.ext == ".py": print('start OK!') self.p = subprocess.Popen(['python', '%s' % self.cmd], stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr, shell=False) else: pass app = Auto_Run(TIME, CMD) ================================================ FILE: utils.py ================================================ from online_net import OnlineNet import printer import time import datetime try: from PIL import Image except ImportError: Image = None from io import BytesIO import webbrowser import re from operator import itemgetter from configloader import ConfigLoader def adjust_for_chinese(str): SPACE = '\N{IDEOGRAPHIC SPACE}' EXCLA = '\N{FULLWIDTH EXCLAMATION MARK}' TILDE = '\N{FULLWIDTH TILDE}' # strings of ASCII and full-width characters (same order) west = ''.join(chr(i) for i in range(ord(' '), ord('~'))) east = SPACE + ''.join(chr(i) for i in range(ord(EXCLA), ord(TILDE))) # build the translation table full = str.maketrans(west, east) str = str.translate(full).rstrip().split('\n') md = f'{str[0]:^10}' return md.translate(full) def CurrentTime(): currenttime = int(time.time()) return str(currenttime) def seconds_until_tomorrow(): today = datetime.date.today() tomorrow = today + datetime.timedelta(days=1) tomorrow_start_time = int(time.mktime(time.strptime(str(tomorrow), '%Y-%m-%d'))) current_time = int(time.mktime(datetime.datetime.now().timetuple())) return tomorrow_start_time - current_time async def WearingMedalInfo(): json_response = await OnlineNet().req('ReqWearingMedal') # print(json_response) if not json_response['code']: data = json_response['data'] if data: # print(data['roominfo']['room_id'], data['today_feed'], data['day_limit']) return [(data['roominfo']['room_id'], int(data['day_limit']) - int(data['today_feed']), data['medal_name']), ] else: # print('暂无佩戴任何勋章') return [] # web api返回值信息少 async def TitleInfo(): json_response = await OnlineNet().req('ReqTitleInfo') dic_title = ConfigLoader().dic_title # print(json_response) if not json_response['code']: data = json_response['data'] for i in data['list']: if i['level']: max = i['level'][1] else: max = '-' print(dic_title[i['title_pic']['id']], i['activity'], i['score'], max) async def fetch_medal(show=True, list_wanted_medal=None): printlist = [] list_medal = [] if show: printlist.append('查询勋章信息') printlist.append( '{} {} {:^12} {:^10} {} {:^6} {}'.format(adjust_for_chinese('勋章'), adjust_for_chinese('主播昵称'), '亲密度', '今日的亲密度', adjust_for_chinese('排名'), '勋章状态', '房间号码')) dic_worn = {'1': '正在佩戴', '0': '待机状态'} json_response = await OnlineNet().req('request_fetchmedal') # print(json_response) if not json_response['code']: for i in json_response['data']['fansMedalList']: if 'roomid' in i: list_medal.append((i['roomid'], int(i['dayLimit']) - int(i['todayFeed']), i['medal_name'], i['level'])) if show: printlist.append('{} {} {:^14} {:^14} {} {:^6} {:^9}'.format(adjust_for_chinese(i['medal_name'] + '|' + str(i['level'])), adjust_for_chinese(i['anchorInfo']['uname']), str(i['intimacy']) + '/' + str(i['next_intimacy']), str(i['todayFeed']) + '/' + str(i['dayLimit']), adjust_for_chinese(str(i['rank'])), dic_worn[str(i['status'])], i['roomid'])) if show: printer.info(printlist, True) if list_wanted_medal is not None: list_return_medal = [] for roomid in list_wanted_medal: for i in list_medal: if i[0] == roomid: list_return_medal.append(i[:3]) break else: list_return_medal = [i[:3] for i in sorted(list_medal, key=itemgetter(3), reverse=True)] return list_return_medal async def send_danmu_msg_web(msg, roomId): json_response = await OnlineNet().req('request_send_danmu_msg_web', msg, roomId) print(json_response) async def find_live_user_roomid(wanted_name): print(wanted_name) def check_name_piece(json_rsp, wanted_name): results = json_rsp['result'] if results is None: # print('屏蔽全名') return None for i in results: real_name = re.sub(r'<[^>]*>', '', i['uname']) # print('去除干扰', real_name) if real_name == wanted_name: print('找到结果', i) return i return None for i in range(len(wanted_name), 0, -1): name_piece = wanted_name[:i] json_rsp = await OnlineNet().req('request_search_biliuser', name_piece) answer = check_name_piece(json_rsp, wanted_name) if answer is not None: return answer['room_id'] # print('结束一次') print('第2备份启用') for i in range(len(wanted_name)): name_piece = wanted_name[i:] json_rsp = await OnlineNet().req('request_search_biliuser', name_piece) answer = check_name_piece(json_rsp, wanted_name) if answer is not None: return answer['room_id'] print('第3备份启用') for i in range(len(wanted_name), 0, -1): name_piece = wanted_name[:i] json_rsp = await OnlineNet().req('request_search_liveuser', name_piece) answer = check_name_piece(json_rsp, wanted_name) if answer is not None: return answer['roomid'] print('第4备份启用') for i in range(len(wanted_name)): name_piece = wanted_name[i:] json_rsp = await OnlineNet().req('request_search_liveuser', name_piece) answer = check_name_piece(json_rsp, wanted_name) if answer is not None: return answer['roomid'] async def fetch_capsule_info(): json_response = await OnlineNet().req('request_fetch_capsule') # print(json_response) if not json_response['code']: data = json_response['data'] if data['colorful']['status']: print(f'梦幻扭蛋币: {data["colorful"]["coin"]}个') else: print('梦幻扭蛋币暂不可用') data = json_response['data'] if data['normal']['status']: print(f'普通扭蛋币: {data["normal"]["coin"]}个') else: print('普通扭蛋币暂不可用') async def open_capsule(count): json_response = await OnlineNet().req('request_open_capsule', count) # print(json_response) if not json_response['code']: # print(json_response['data']['text']) for i in json_response['data']['text']: print(i) async def watch_living_video(cid): import sound sound.set_honors_silent_switch(False) sound.set_volume(1) sound.play_effect('piano:D3') json_response = await OnlineNet().req('request_playurl', cid) print(json_response) if not json_response['code']: data = json_response['data'] print(data) webbrowser.open(data) async def fetch_user_info(): json_response = await OnlineNet().req('request_fetch_user_info') json_response_ios = await OnlineNet().req('request_fetch_user_infor_ios') print('[{}] 查询用户信息'.format(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))) if not json_response_ios['code']: gold_ios = json_response_ios['data']['gold'] # print(json_response_ios) if not json_response['code']: data = json_response['data'] # print(data) userInfo = data['userInfo'] userCoinIfo = data['userCoinIfo'] uname = userInfo['uname'] achieve = data['achieves'] user_level = userCoinIfo['user_level'] silver = userCoinIfo['silver'] gold = userCoinIfo['gold'] identification = bool(userInfo['identification']) mobile_verify = bool(userInfo['mobile_verify']) user_next_level = userCoinIfo['user_next_level'] user_intimacy = userCoinIfo['user_intimacy'] user_next_intimacy = userCoinIfo['user_next_intimacy'] user_level_rank = userCoinIfo['user_level_rank'] billCoin = userCoinIfo['coins'] bili_coins = userCoinIfo['bili_coins'] print('# 用户名', uname) size = 100, 100 response_face = await OnlineNet().req('request_load_img', userInfo['face']) if Image is not None: img = Image.open(BytesIO(await response_face.read())) img.thumbnail(size) try: img.show() except: pass print(f'# 手机认证状况 {mobile_verify} | 实名认证状况 {identification}') print('# 银瓜子', silver) print('# 通用金瓜子', gold) print('# ios可用金瓜子', gold_ios) print('# 硬币数', billCoin) print('# b币数', bili_coins) print('# 成就值', achieve) print('# 等级值', user_level, '———>', user_next_level) print('# 经验值', user_intimacy) print('# 剩余值', user_next_intimacy - user_intimacy) arrow = int(user_intimacy * 30 / user_next_intimacy) line = 30 - arrow percent = user_intimacy / user_next_intimacy * 100.0 process_bar = '# [' + '>' * arrow + '-' * line + ']' + '%.2f' % percent + '%' print(process_bar) print('# 等级榜', user_level_rank) async def fetch_bag_list(verbose=False, bagid=None, show=True): json_response = await OnlineNet().req('request_fetch_bag_list') gift_list = [] # print(json_response) if show: print('[{}] 查询可用礼物'.format(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))) for i in json_response['data']['list']: bag_id = i['bag_id'] gift_id = i['gift_id'] gift_num = i['gift_num'] gift_name = i['gift_name'] expireat = i['expire_at'] left_time = (expireat - json_response['data']['time']) if not expireat: left_days = '+∞'.center(6) left_time = None else: left_days = round(left_time / 86400, 1) if bagid is not None: if bag_id == int(bagid): return gift_id, gift_num else: if verbose: print(f'# 编号为{bag_id}的{gift_name:^3}X{gift_num:^4} (在{left_days:^6}天后过期)') elif show: print(f'# {gift_name:^3}X{gift_num:^4} (在{left_days:^6}天后过期)') gift_list.append([gift_id, gift_num, bag_id, left_time]) # print(gift_list) return gift_list async def check_taskinfo(): json_response = await OnlineNet().req('request_check_taskinfo') # print(json_response) if not json_response['code']: data = json_response['data'] double_watch_info = data['double_watch_info'] box_info = data['box_info'] sign_info = data['sign_info'] live_time_info = data['live_time_info'] print('双端观看直播:') if double_watch_info['status'] == 1: print('# 该任务已完成,但未领取奖励') elif double_watch_info['status'] == 2: print('# 该任务已完成,已经领取奖励') else: print('# 该任务未完成') if double_watch_info['web_watch'] == 1: print('## 网页端观看任务已完成') else: print('## 网页端观看任务未完成') if double_watch_info['mobile_watch'] == 1: print('## 移动端观看任务已完成') else: print('## 移动端观看任务未完成') print('直播在线宝箱:') if box_info['status'] == 1: print('# 该任务已完成') else: print('# 该任务未完成') print(f'## 一共{box_info["max_times"]}次重置次数,当前为第{box_info["freeSilverTimes"]}次第{box_info["type"]}个礼包(每次3个礼包)') print('每日签到:') if sign_info['status'] == 1: print('# 该任务已完成') else: print('# 该任务未完成') if sign_info['signDaysList'] == list(range(1, sign_info['curDay'] + 1)): print('# 当前全勤') else: print('# 出现断签') print('直播奖励:') if live_time_info['status'] == 1: print('# 已完成') else: print('# 未完成(目前本项目未实现自动完成直播任务)') async def check_room(roomid): json_response = await OnlineNet().req('request_check_room', roomid) if not json_response['code']: # print(json_response) print('查询结果:') data = json_response['data'] if not data['short_id']: print('# 此房间无短房号') else: print(f'# 短号为:{data["short_id"]}') print(f'# 真实房间号为:{data["room_id"]}') return data['room_id'] # 房间不存在 elif json_response['code'] == 60004: print(json_response['msg']) async def send_gift_web(roomid, num_wanted, bagid, giftid=None): if giftid is None: giftid, num_owned = await fetch_bag_list(False, bagid) num_wanted = min(num_owned, num_wanted) if not num_wanted: return json_response = await OnlineNet().req('request_check_room', roomid) ruid = json_response['data']['uid'] biz_id = json_response['data']['room_id'] # 200027 不足数目 json_response1 = await OnlineNet().req('request_send_gift_web', giftid, num_wanted, bagid, ruid, biz_id) if not json_response1['code']: # print(json_response1['data']) print(f'# 送出礼物: {json_response1["data"]["gift_name"]}X{json_response1["data"]["gift_num"]}') else: print("# 错误", json_response1['msg'], roomid, num_wanted, bagid, giftid) async def fetch_liveuser_info(real_roomid): json_response = await OnlineNet().req('request_fetch_liveuser_info', real_roomid) if not json_response['code']: data = json_response['data'] # print(data) print(f'# 主播姓名 {data["info"]["uname"]}') uid = data['level']['uid'] # str json_response_fan = await OnlineNet().req('request_fetch_fan', real_roomid, uid) # print(json_response_fan) data_fan = json_response_fan['data'] if not json_response_fan['code'] and data_fan['medal']['status'] == 2: print(f'# 勋章名字: {data_fan["list"][0]["medal_name"]}') else: print('# 该主播暂时没有开通勋章') # print(json_response_fan) size = 100, 100 response_face = await OnlineNet().req('request_load_img', data['info']['face']) if Image is not None: img = Image.open(BytesIO(await response_face.read())) img.thumbnail(size) try: img.show() except: pass async def enter_room(roomid): json_response = await OnlineNet().req('request_check_room', roomid) if not json_response['code']: data = json_response['data'] param1 = data['is_hidden'] param2 = data['is_locked'] param3 = data['encrypted'] if any((param1, param2, param3)): printer.info([f'抽奖脚本检测到房间{roomid:^9}为异常房间'], True) printer.warn(f'抽奖脚本检测到房间{roomid:^9}为异常房间') return False else: await OnlineNet().req('post_watching_history', roomid) return True async def GiveCoin2Av(video_id, num): if num not in (1, 2): return False # 10004 稿件已经被删除 # 34005 超过,满了 # -104 不足硬币 json_rsp = await OnlineNet().req('ReqGiveCoin2Av', video_id, num) code = json_rsp['code'] if not code: print(f'给视频av{video_id}投{num}枚硬币成功') return True else: print('投币失败', json_rsp['message']) if code == -104: return None return False async def GetTopVideoList(): text_rsp = await OnlineNet().req('req_fetch_av') list_av = re.findall(r'(?<=www.bilibili.com/video/av)\d+(?=/)', text_rsp) list_av = list(set(list_av)) return list_av async def fetch_uper_video(list_mid): list_av = [] for mid in list_mid: json_rsp = await OnlineNet().req('req_fetch_uper_video', mid, 1) # print(json_rsp) data = json_rsp['data'] pages = data['pages'] if data['vlist']: list_av += [av['aid'] for av in data['vlist']] for page in range(2, pages + 1): json_rsp = await OnlineNet().req('req_fetch_uper_video', mid, page) # print(json_rsp) data = json_rsp['data'] list_av += [av['aid'] for av in data['vlist']] # print(len(list_av), list_av) return list_av async def GetVideoCid(video_aid): json_rsp = await OnlineNet().req('ReqVideoCid', video_aid) # print(json_rsp[0]['cid']) return (json_rsp[0]['cid']) async def GetRewardInfo(show=True): json_rsp = await OnlineNet().req('ReqMasterInfo') data = json_rsp['data'] login = data['login'] watch_av = data['watch_av'] coins_av = data['coins_av'] share_av = data['share_av'] level_info = data["level_info"] current_exp = level_info['current_exp'] next_exp = level_info['next_exp'] if next_exp == -1: next_exp = current_exp print(f'# 主站等级值 {level_info["current_level"]}') print(f'# 主站经验值 {level_info["current_exp"]}') print(f'# 主站剩余值 {- current_exp + next_exp}') arrow = int(current_exp * 30 / next_exp) line = 30 - arrow percent = current_exp / next_exp * 100.0 process_bar = '# [' + '>' * arrow + '-' * line + ']' + '%.2f' % percent + '%' print(process_bar) if show: print(f'每日登陆:{login} 每日观看:{watch_av} 每日投币经验:{coins_av}/50 每日分享:{share_av}') return login, watch_av, coins_av, share_av async def FetchRoomArea(roomid): json_response = await OnlineNet().req('ReqRoomInfo', roomid) if not json_response['code']: # print(json_response) # print(json_response['data']['parent_area_id']) return json_response['data']['parent_area_id'] async def check_room_for_danmu(room_id, area_id): json_response = await OnlineNet().req('request_check_room', room_id) data = json_response['data'] is_hidden = data['is_hidden'] is_locked = data['is_locked'] is_encrypted = data['encrypted'] if any((is_hidden, is_locked, is_encrypted)): is_normal = False else: is_normal = True json_response = await OnlineNet().req('ReqRoomInfo', room_id) data = json_response['data'] is_open = True if data['live_status'] == 1 else False current_area_id = data['parent_area_id'] # print(is_hidden, is_locked, is_encrypted, is_open, current_area_id) is_ok = (area_id == current_area_id) and is_normal and is_open return is_ok