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
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
SYMBOL INDEX (280 symbols across 15 files)
FILE: OnlineHeart.py
function CurrentTime (line 7) | def CurrentTime():
function heartbeat (line 12) | async def heartbeat():
function draw_lottery (line 21) | async def draw_lottery():
function run (line 59) | async def run():
FILE: Silver.py
function GetAward (line 8) | async def GetAward():
function GetAward_black (line 19) | async def GetAward_black():
function run (line 35) | async def run():
FILE: Tasks.py
function Daily_bag (line 12) | async def Daily_bag():
function DoSign (line 21) | async def DoSign():
function Daily_Task (line 32) | async def Daily_Task():
function Sign1Group (line 42) | async def Sign1Group(i1, i2):
function link_sign (line 52) | async def link_sign():
function send_expiring_gift (line 59) | async def send_expiring_gift():
function send_medal_gift (line 87) | async def send_medal_gift():
function send_gift (line 108) | async def send_gift():
function full_intimate (line 113) | async def full_intimate(list_gift, list_medal):
function doublegain_coin2silver (line 136) | async def doublegain_coin2silver():
function sliver2coin (line 143) | async def sliver2coin():
function GetVideoExp (line 166) | async def GetVideoExp(list_topvideo):
function GiveCoinTask (line 172) | async def GiveCoinTask(coin_remain, list_topvideo):
function GetVideoShareExp (line 186) | async def GetVideoShareExp(list_topvideo):
function BiliMainTask (line 191) | async def BiliMainTask():
function check (line 210) | async def check(id):
function judge_case (line 232) | def judge_case(voted, percent):
function judge (line 256) | async def judge():
function init (line 315) | def init():
FILE: bili_console.py
function fetch_real_roomid (line 14) | def fetch_real_roomid(roomid):
class Biliconsole (line 22) | class Biliconsole(Cmd):
method __init__ (line 25) | def __init__(self, loop):
method guide_of_console (line 29) | def guide_of_console(self):
method default (line 48) | def default(self, line):
method emptyline (line 51) | def emptyline(self):
method do_1 (line 54) | def do_1(self, line):
method do_2 (line 57) | def do_2(self, line):
method do_3 (line 60) | def do_3(self, line):
method do_4 (line 63) | def do_4(self, line):
method do_5 (line 66) | def do_5(self, line):
method do_6 (line 69) | def do_6(self, line):
method do_7 (line 75) | def do_7(self, line):
method do_8 (line 81) | def do_8(self, line):
method do_9 (line 90) | def do_9(self, line):
method do_10 (line 95) | def do_10(self, line):
method do_11 (line 102) | def do_11(self, line):
method do_12 (line 107) | def do_12(self, line):
method do_13 (line 110) | def do_13(self, line):
method do_14 (line 114) | def do_14(self, line):
method do_15 (line 122) | def do_15(self, line):
method do_16 (line 125) | def do_16(self, line):
method do_17 (line 128) | def do_17(self, line):
method do_18 (line 135) | def do_18(self, line):
method do_19 (line 140) | def do_19(self, line):
method do_check (line 147) | def do_check(self, line):
method append2list_console (line 151) | def append2list_console(self, request):
method excute_async (line 155) | async def excute_async(self, i):
FILE: bilibili.py
function CurrentTime (line 18) | def CurrentTime():
function randomint (line 23) | def randomint():
function cnn_captcha (line 27) | def cnn_captcha(content):
function input_captcha (line 37) | def input_captcha(content):
class bilibili (line 51) | class bilibili():
method __new__ (line 55) | def __new__(cls, *args, **kw):
method bili_session (line 67) | def bili_session(self):
method other_session (line 74) | def other_session(self):
method login_session (line 81) | def login_session(self):
method calc_sign (line 87) | def calc_sign(self, str):
method load_session (line 93) | def load_session(dic):
method login_session_post (line 102) | def login_session_post(self, url, headers=None, data=None, params=None):
method login_session_get (line 116) | def login_session_get(self, url, headers=None, data=None, params=None):
method get_json_rsp (line 130) | async def get_json_rsp(self, rsp, url):
method get_text_rsp (line 151) | async def get_text_rsp(self, rsp, url):
method bili_session_post (line 158) | async def bili_session_post(self, url, headers=None, data=None, params...
method other_session_get (line 170) | async def other_session_get(self, url, headers=None, data=None, params...
method other_session_post (line 182) | async def other_session_post(self, url, headers=None, data=None, param...
method bili_session_get (line 194) | async def bili_session_get(self, url, headers=None, data=None, params=...
method session_text_get (line 206) | async def session_text_get(self, url, headers=None, data=None, params=...
method request_playurl (line 219) | async def request_playurl(cid):
method request_search_liveuser (line 228) | async def request_search_liveuser(name):
method request_search_biliuser (line 235) | async def request_search_biliuser(name):
method request_fetch_capsule (line 242) | async def request_fetch_capsule():
method request_open_capsule (line 249) | async def request_open_capsule(count):
method request_logout (line 261) | def request_logout():
method request_doublegain_coin2silver (line 276) | async def request_doublegain_coin2silver():
method post_watching_history (line 285) | async def post_watching_history(room_id):
method silver2coin_web (line 296) | async def silver2coin_web():
method silver2coin_app (line 307) | async def silver2coin_app():
method request_fetch_fan (line 316) | async def request_fetch_fan(real_roomid, uid):
method request_check_room (line 323) | async def request_check_room(roomid):
method request_fetch_bag_list (line 330) | async def request_fetch_bag_list():
method request_check_taskinfo (line 337) | async def request_check_taskinfo():
method request_send_gift_web (line 344) | async def request_send_gift_web(giftid, giftnum, bagid, ruid, biz_id):
method request_fetch_user_info (line 366) | async def request_fetch_user_info():
method request_fetch_user_infor_ios (line 373) | async def request_fetch_user_infor_ios():
method request_fetch_liveuser_info (line 381) | async def request_fetch_liveuser_info(real_roomid):
method request_load_img (line 388) | async def request_load_img(url):
method request_send_danmu_msg_web (line 392) | async def request_send_danmu_msg_web(msg, roomId):
method request_fetchmedal (line 410) | async def request_fetchmedal():
method ReqWearingMedal (line 417) | async def ReqWearingMedal():
method ReqTitleInfo (line 428) | async def ReqTitleInfo():
method request_getkey (line 437) | def request_getkey():
method normal_login (line 447) | def normal_login(username, password, captcha=None):
method get_captcha (line 459) | def get_captcha(username, password):
method request_check_token (line 472) | def request_check_token():
method request_refresh_token (line 483) | def request_refresh_token():
method get_giftlist_of_storm (line 496) | async def get_giftlist_of_storm(roomid):
method get_gift_of_storm (line 503) | async def get_gift_of_storm(id):
method get_gift_of_events_web (line 517) | async def get_gift_of_events_web(text1, text2, raffleid):
method get_gift_of_events_app (line 530) | async def get_gift_of_events_app(text1, raffleid):
method get_gift_of_TV (line 540) | async def get_gift_of_TV(real_roomid, TV_raffleid):
method get_gift_of_TV_app (line 554) | async def get_gift_of_TV_app(real_roomid, raffle_id, raffle_type):
method get_gift_of_guard (line 566) | async def get_gift_of_guard(roomid, id):
method get_giftlist_of_events (line 579) | async def get_giftlist_of_events(text1):
method get_giftlist_of_TV (line 589) | async def get_giftlist_of_TV(real_roomid):
method get_giftlist_of_guard (line 596) | async def get_giftlist_of_guard(roomid):
method get_activity_result (line 603) | async def get_activity_result(activity_roomid, activity_raffleid):
method get_TV_result (line 610) | async def get_TV_result(TV_roomid, TV_raffleid):
method pcpost_heartbeat (line 617) | async def pcpost_heartbeat():
method apppost_heartbeat (line 625) | async def apppost_heartbeat():
method heart_gift (line 637) | async def heart_gift():
method get_lotterylist (line 644) | async def get_lotterylist(i):
method get_gift_of_lottery (line 651) | async def get_gift_of_lottery(i, g):
method get_time_about_silver (line 658) | async def get_time_about_silver():
method get_silver (line 668) | async def get_silver(timestart, timeend):
method get_dailybag (line 678) | async def get_dailybag():
method get_dosign (line 685) | async def get_dosign():
method get_dailytask (line 692) | async def get_dailytask():
method get_grouplist (line 700) | async def get_grouplist():
method assign_group (line 707) | async def assign_group(i1, i2):
method gift_list (line 716) | async def gift_list():
method req_realroomid (line 722) | async def req_realroomid(areaid):
method req_room_init (line 728) | async def req_room_init(roomid):
method ReqRoomInfo (line 734) | async def ReqRoomInfo(roomid):
method ReqGiveCoin2Av (line 740) | async def ReqGiveCoin2Av(self, video_id, num):
method Heartbeat (line 755) | async def Heartbeat(self, aid, cid):
method ReqMasterInfo (line 763) | async def ReqMasterInfo(self):
method ReqVideoCid (line 768) | async def ReqVideoCid(self, video_aid):
method DailyVideoShare (line 773) | async def DailyVideoShare(self, video_aid):
method req_fetch_uper_video (line 779) | async def req_fetch_uper_video(self, mid, page):
method req_fetch_av (line 784) | async def req_fetch_av(self):
method req_vote_case (line 788) | async def req_vote_case(self, id, vote):
method req_fetch_case (line 803) | async def req_fetch_case(self):
method req_check_voted (line 812) | async def req_check_voted(self, id):
FILE: bilitimer.py
function CurrentTime (line 6) | def CurrentTime():
class BiliTimer (line 11) | class BiliTimer:
method __new__ (line 15) | def __new__(cls, loop=None):
method excute_async (line 21) | def excute_async(self, i):
method call_after (line 26) | def call_after(func, delay):
method append2list_jobs (line 32) | def append2list_jobs(func, time_expected, tuple_values):
FILE: configloader.py
function hex_to_rgb_percent (line 5) | def hex_to_rgb_percent(hex_str):
function rgb_to_percent (line 10) | def rgb_to_percent(rgb_list):
class ConfigLoader (line 14) | class ConfigLoader():
method __new__ (line 18) | def __new__(cls, fileDir=None):
method write2bilibili (line 44) | def write2bilibili(self, dic):
method load_bilibili (line 52) | def load_bilibili(self):
method load_color (line 65) | def load_color(self):
method load_user (line 77) | def load_user(self):
method load_title (line 82) | def load_title(self):
FILE: connect.py
function get_one (line 10) | async def get_one(areaid):
class connect (line 31) | class connect():
method __new__ (line 35) | def __new__(cls, *args, **kw):
method run (line 43) | async def run(self):
method reconnect (line 68) | async def reconnect(roomid):
class RaffleConnect (line 76) | class RaffleConnect():
method __init__ (line 77) | def __init__(self, areaid):
method run (line 82) | async def run(self):
class YjConnection (line 110) | class YjConnection():
method __init__ (line 111) | def __init__(self):
method run (line 116) | async def run(self):
FILE: danmu.py
class BaseDanmu (line 12) | class BaseDanmu():
method __init__ (line 15) | def __init__(self, room_id, area_id):
method room_id (line 22) | def room_id(self):
method room_id (line 27) | def room_id(self, room_id):
method _wrap_str (line 32) | def _wrap_str(self, opt, body, len_header=16, ver=1, seq=1):
method _send_bytes (line 39) | async def _send_bytes(self, bytes_data):
method _read_bytes (line 49) | async def _read_bytes(self):
method open (line 65) | async def open(self):
method heart_beat (line 76) | async def heart_beat(self):
method read_datas (line 85) | async def read_datas(self):
method close (line 119) | async def close(self):
method handle_danmu (line 127) | def handle_danmu(self, body):
class DanmuPrinter (line 131) | class DanmuPrinter(BaseDanmu):
method handle_danmu (line 132) | def handle_danmu(self, body):
class DanmuRaffleHandler (line 142) | class DanmuRaffleHandler(BaseDanmu):
method check_area (line 143) | async def check_area(self):
method handle_danmu (line 154) | def handle_danmu(self, body):
class YjMonitorHandler (line 206) | class YjMonitorHandler(BaseDanmu):
method __init__ (line 207) | def __init__(self, room_id, area_id):
method __base2dec (line 213) | def __base2dec(self, str_num, base=110):
method __reverse (line 219) | def __reverse(self, msg):
method __combine_piece (line 231) | def __combine_piece(self, uid, msg):
method handle_danmu (line 250) | def handle_danmu(self, body):
FILE: online_net.py
function calc_name_passw (line 10) | def calc_name_passw(key, Hash, username, password):
function LoginWithPwd (line 18) | def LoginWithPwd():
function login (line 59) | def login():
function logout (line 67) | def logout():
function check_token (line 75) | def check_token():
function RefreshToken (line 86) | def RefreshToken():
function HandleExpire (line 115) | def HandleExpire():
class OnlineNet (line 126) | class OnlineNet():
method __new__ (line 129) | def __new__(cls, *args, **kw):
method is_online (line 138) | def is_online(self):
method is_online (line 142) | def is_online(self, setting):
method req (line 149) | async def req(self, str_func, *args):
FILE: printer.py
class BasePrinter (line 8) | class BasePrinter():
method init_config (line 9) | def init_config(self):
method control_printer (line 16) | def control_printer(self, danmu_control=None, debug_control=None):
method timestamp (line 24) | def timestamp(self):
method info (line 28) | def info(self, list_msg, tag_time=False):
method warn (line 34) | def warn(self, msg):
method debug (line 39) | def debug(self, msg):
method error (line 43) | def error(self, msg):
class PythonistaPrinter (line 48) | class PythonistaPrinter(BasePrinter):
method hex_to_rgb_percent (line 51) | def hex_to_rgb_percent(self, hex_str):
method print_danmu (line 55) | def print_danmu(self, dic_msg, type='normal'):
class NormalPrinter (line 107) | class NormalPrinter(BasePrinter):
method print_danmu (line 109) | def print_danmu(self, dic_msg, type='normal'):
function init_config (line 151) | def init_config():
function info (line 155) | def info(list_msg, tag_time=False):
function warn (line 159) | def warn(msg):
function error (line 163) | def error(msg):
function debug (line 167) | def debug(msg):
function print_danmu (line 171) | def print_danmu(dic_msg, type='normal'):
function control_printer (line 175) | def control_printer(danmu_control=None, debug_control=None):
FILE: rafflehandler.py
function CurrentTime (line 11) | def CurrentTime():
class Rafflehandler (line 16) | class Rafflehandler:
method __new__ (line 20) | def __new__(cls, *args, **kw):
method run (line 27) | async def run(self):
method Put2Queue (line 55) | def Put2Queue(value, func):
method Put2Queue_wait (line 62) | async def Put2Queue_wait(value, func):
method getlist (line 69) | def getlist():
method add2raffle_id (line 72) | def add2raffle_id(self, raffle_id):
method check_duplicate (line 79) | def check_duplicate(self, raffle_id):
function handle_1_TV_raffle (line 83) | async def handle_1_TV_raffle(num, real_roomid, raffleid, raffle_type):
function handle_1_guard_raffle (line 117) | async def handle_1_guard_raffle(num, roomid, raffleid):
function handle_1_storm_raffle (line 129) | async def handle_1_storm_raffle(id):
function handle_1_activity_raffle (line 134) | async def handle_1_activity_raffle(num, text1, raffleid):
function handle_1_room_TV (line 167) | async def handle_1_room_TV(real_roomid):
function handle_1_room_storm (line 190) | async def handle_1_room_storm(roomid):
function handle_1_room_activity (line 202) | async def handle_1_room_activity(text1):
function handle_1_room_guard (line 228) | async def handle_1_room_guard(roomid, raffleid=None):
function handle_1_TV_raffle_black (line 265) | async def handle_1_TV_raffle_black(num, real_roomid, raffleid, raffle_ty...
function handle_1_activity_raffle_black (line 294) | async def handle_1_activity_raffle_black(num, text1, raffleid):
FILE: statistics.py
class Statistics (line 1) | class Statistics:
method __new__ (line 4) | def __new__(cls, area_num=0):
method add_to_result (line 21) | def add_to_result(type, num):
method getlist (line 26) | def getlist():
method append_to_activitylist (line 46) | def append_to_activitylist(raffleid, text1, time=''):
method append_to_TVlist (line 55) | def append_to_TVlist(raffleid, real_roomid, time=''):
method append_to_guardlist (line 64) | def append_to_guardlist():
method append2joined_raffle (line 69) | def append2joined_raffle(type, num=1):
method add2pushed_raffle (line 74) | def add2pushed_raffle(raffle_name, broadcast_type=0, num=1):
method check_TVlist (line 83) | def check_TVlist(real_roomid, raffleid):
method check_activitylist (line 90) | def check_activitylist(real_roomid, raffleid):
method checklist (line 97) | def checklist():
FILE: ugly_auto_reboot.py
class Auto_Run (line 9) | class Auto_Run():
method __init__ (line 10) | def __init__(self, sleep_time, cmd):
method run (line 32) | def run(self):
FILE: utils.py
function adjust_for_chinese (line 16) | def adjust_for_chinese(str):
function CurrentTime (line 32) | def CurrentTime():
function seconds_until_tomorrow (line 37) | def seconds_until_tomorrow():
function WearingMedalInfo (line 45) | async def WearingMedalInfo():
function TitleInfo (line 60) | async def TitleInfo():
function fetch_medal (line 74) | async def fetch_medal(show=True, list_wanted_medal=None):
function send_danmu_msg_web (line 104) | async def send_danmu_msg_web(msg, roomId):
function find_live_user_roomid (line 109) | async def find_live_user_roomid(wanted_name):
function fetch_capsule_info (line 158) | async def fetch_capsule_info():
function open_capsule (line 175) | async def open_capsule(count):
function watch_living_video (line 184) | async def watch_living_video(cid):
function fetch_user_info (line 197) | async def fetch_user_info():
function fetch_bag_list (line 250) | async def fetch_bag_list(verbose=False, bagid=None, show=True):
function check_taskinfo (line 282) | async def check_taskinfo():
function check_room (line 333) | async def check_room(roomid):
function send_gift_web (line 351) | async def send_gift_web(roomid, num_wanted, bagid, giftid=None):
function fetch_liveuser_info (line 369) | async def fetch_liveuser_info(real_roomid):
function enter_room (line 396) | async def enter_room(roomid):
function GiveCoin2Av (line 413) | async def GiveCoin2Av(video_id, num):
function GetTopVideoList (line 431) | async def GetTopVideoList():
function fetch_uper_video (line 438) | async def fetch_uper_video(list_mid):
function GetVideoCid (line 456) | async def GetVideoCid(video_aid):
function GetRewardInfo (line 462) | async def GetRewardInfo(show=True):
function FetchRoomArea (line 487) | async def FetchRoomArea(roomid):
function check_room_for_danmu (line 496) | async def check_room_for_danmu(room_id, area_id):
Condensed preview — 26 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (150K chars).
[
{
"path": ".gitignore",
"chars": 23,
"preview": "\n.DS_Store\n*.iml\n*.xml\n"
},
{
"path": "Dockerfile",
"chars": 1271,
"preview": "FROM python:3.6-alpine\n\n\nENV LIBRARY_PATH=/lib:/usr/lib \\\n USER_NAME='' \\\n USER_PASSWORD=''\n\nWORKDIR /app\n\nRUN ech"
},
{
"path": "LICENSE",
"chars": 1066,
"preview": "MIT License\n\nCopyright (c) 2018 Dawnspace\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
},
{
"path": "OnlineHeart.py",
"chars": 2252,
"preview": "from online_net import OnlineNet\nimport time\nimport asyncio\nimport printer\n\n\ndef CurrentTime():\n currenttime = int(ti"
},
{
"path": "README.md",
"chars": 2404,
"preview": "# bilibili-live-tools\n:no_entry: [DEPRECATED] \n~~单用户比利脚本~~ \n***1.本项目作为老项目已经被新项目取代 https://github.com/yjqiang/bili2.0**"
},
{
"path": "Silver.py",
"chars": 2193,
"preview": "from online_net import OnlineNet\nimport utils\nimport printer\nimport asyncio\n\n\n# 领取银瓜子\nasync def GetAward():\n temp = a"
},
{
"path": "Tasks.py",
"chars": 10836,
"preview": "from online_net import OnlineNet\nimport asyncio\nfrom configloader import ConfigLoader\nimport utils\nimport printer\nfrom b"
},
{
"path": "bili_console.py",
"chars": 5462,
"preview": "import sys\nimport utils\nfrom statistics import Statistics\nfrom connect import connect\nimport printer\nfrom configloader i"
},
{
"path": "bilibili.py",
"chars": 33172,
"preview": "import sys\nfrom configloader import ConfigLoader\nimport hashlib\nimport time\nimport requests\nimport base64\nimport aiohttp"
},
{
"path": "bilitimer.py",
"chars": 943,
"preview": "import asyncio\nimport time\nimport printer\n\n\ndef CurrentTime():\n currenttime = int(time.time())\n return currenttime"
},
{
"path": "conf/bilibili.toml",
"chars": 936,
"preview": "appkey = \"1d8b6e7d45233436\"\nactionKey = \"appkey\"\nbuild = \"520001\"\ndevice = \"android\"\nmobi_app = \"android\"\nplatform = \"an"
},
{
"path": "conf/color.toml",
"chars": 1484,
"preview": "[user-level]\nul0 = \"#646c7a\"\nul1 = \"#969696\"\nul2 = \"#969696\"\nul3 = \"#969696\"\nul4 = \"#969696\"\nul5 = \"#969696\"\nul6 = \"#969"
},
{
"path": "conf/title.toml",
"chars": 3945,
"preview": "title-176-1 = \"凯旋\"\ntitle-175-1 = \"骑士之心\"\ntitle-175-2 = \"永恒誓约\"\ntitle-174-1 = \"幻影\"\ntitle-174-2 = \"光之护卫\"\ntitle-173-1 = \"预言家\""
},
{
"path": "conf/title_init.py",
"chars": 322,
"preview": "import requests\nimport toml\n\n\nrsp = requests.get('https://api.live.bilibili.com/rc/v1/Title/webTitles')\nrsp.encoding = '"
},
{
"path": "conf/user.toml",
"chars": 854,
"preview": "[print_control]\ndanmu = false\ndebug = false\n\n[task_control]\n# 清理即将过期礼物,请true之后一定要把紧随其后的room设置为真实房间号\nclean-expiring-gift "
},
{
"path": "configloader.py",
"chars": 3055,
"preview": "import toml\n\n\n# \"#969696\"\ndef hex_to_rgb_percent(hex_str):\n return tuple(int(n, 16)/255 for n in (hex_str[1:3], hex_s"
},
{
"path": "connect.py",
"chars": 5651,
"preview": "import asyncio\nimport utils\nimport danmu\nimport printer\nfrom online_net import OnlineNet\nfrom configloader import Config"
},
{
"path": "danmu.py",
"chars": 10881,
"preview": "from statistics import Statistics\nimport printer\nimport rafflehandler\nimport utils\nimport asyncio\nimport struct\nimport j"
},
{
"path": "online_net.py",
"chars": 5877,
"preview": "from bilibili import bilibili\nfrom configloader import ConfigLoader\nimport rsa\nimport base64\nfrom urllib import parse\nim"
},
{
"path": "printer.py",
"chars": 5335,
"preview": "import sys\nimport time\nfrom configloader import ConfigLoader\nif sys.platform == 'ios':\n import console\n\n \nclas"
},
{
"path": "rafflehandler.py",
"chars": 12438,
"preview": "from online_net import OnlineNet\nfrom statistics import Statistics\nimport printer\nimport utils\nimport asyncio\nimport tim"
},
{
"path": "requirements.txt",
"chars": 53,
"preview": "requests\nrsa\naiohttp\n# Pillow 当你需要自己输入验证码的时候请安装\ntoml\n"
},
{
"path": "run.py",
"chars": 1519,
"preview": "import OnlineHeart\nimport Silver\nimport Tasks\nimport connect\nfrom rafflehandler import Rafflehandler\nimport asyncio\nimpo"
},
{
"path": "statistics.py",
"chars": 3449,
"preview": "class Statistics:\n instance = None\n\n def __new__(cls, area_num=0):\n if not cls.instance:\n cls.in"
},
{
"path": "ugly_auto_reboot.py",
"chars": 1022,
"preview": "import subprocess\nimport time\nimport sys\n\nTIME = 3600\nCMD = \"run.py\"\n\n\nclass Auto_Run():\n def __init__(self, sleep_ti"
},
{
"path": "utils.py",
"chars": 18206,
"preview": "from online_net import OnlineNet\nimport printer\nimport time\nimport datetime\ntry:\n from PIL import Image\nexcept Import"
}
]
About this extraction
This page contains the full source code of the yjqiang/bilibili-live-tools GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 26 files (131.5 KB), approximately 37.3k tokens, and a symbol index with 280 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.