diff --git a/0.py b/0.py deleted file mode 100644 index efc4439..0000000 --- a/0.py +++ /dev/null @@ -1,75 +0,0 @@ -from config_loader import ConfigLoader -from task import RaffleHandler, Task, StateTask -from webhub.web_hub import WebHub, HostWebHub -import os -import sys -from bili_user.user import User -import asyncio -import printer -import connect -import bili_console -import threading -import bili_stats -from cdn import Host -from bili_user.super_user import SuperUser - -if sys.platform == 'win32': - loop = asyncio.ProactorEventLoop() - asyncio.set_event_loop(loop) -else: - loop = asyncio.get_event_loop() -fileDir = os.path.dirname(os.path.realpath('__file__')) -file_color = f'{fileDir}/config/color.toml' -file_user = f'{fileDir}/config/user.toml' -file_bili = f'{fileDir}/config/bili.toml' -file_ip = f'{fileDir}/config/ips.toml' -cfg = ConfigLoader(file_color, file_user, file_bili, file_ip) - -dict_user = cfg.read_user() -dict_bili = cfg.read_bili() -dict_color = cfg.read_color() -dict_ip = cfg.read_ip() -printer.init_config(dict_color, dict_user['print_control']['danmu']) - -users = [] -task_control = dict_user['task_control'] -if len(dict_user['users']) < 10: - for i, user_info in enumerate(dict_user['users']): - webhub = WebHub(i, user_info, dict_bili) - users.append(User(i, user_info, webhub, task_control)) -else: - host = Host(dict_ip['list_ips']) - loop.run_until_complete(host.proxies_filter()) - for i, user_info in enumerate(dict_user['users']): - webhub = HostWebHub(i, user_info, dict_bili, host) - users.append(User(i, user_info, webhub, task_control)) - -danmu_connection = connect.connect(dict_user['other_control']['default_monitor_roomid']) -list_raffle_connection = [connect.RaffleConnect(i) for i in range(1, 5)] -bili_stats.init_area_num(4) -list_raffle_connection_task = [i.run() for i in list_raffle_connection] -yjconnection = connect.YjConnection(dict_user['other_control']['raffle_minitor_roomid']) - -var_super_user = SuperUser(users[0].webhub) -raffle = RaffleHandler(users, var_super_user, loop, True) -normal_task = Task(users, var_super_user, loop) -state_task = StateTask(users, var_super_user, loop) - -loop.run_until_complete(asyncio.wait([normal_task.call_one_by_one('handle_login_status', ())])) - -var_console = bili_console.Biliconsole(users, var_super_user, loop) -console_thread = threading.Thread(target=var_console.cmdloop) -console_thread.start() -normal_task.init() - -tasks = [ - raffle.join_raffle(), - danmu_connection.run(), - state_task.run_workstate(), - state_task.run_timestate(), - yjconnection.run() -] - - -loop.run_until_complete(asyncio.wait(tasks + list_raffle_connection_task)) -console_thread.join() diff --git a/LICENSE b/LICENSE deleted file mode 100644 index ab60297..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 - -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. diff --git a/README.md b/README.md index 85f3e2f..7a75242 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,7 @@ -# bili2.0 -比利脚本多用户版本 ----------- - 使用步骤(正式版之前): - 1.安装python 3.6(python 3.7 websockets暂时未正式支持,除此之外应该没问题) - 2.安装一些依赖库 - 3.导入多用户到user.toml - 4.运行0.py - - - 版本更新: - v0.1: - 初步实现大部分单用户的功能 - v0.2: - 对小黑屋进行处理 - 试图解决403等问题 - 添加原来的功能支持 - v1.0: - 正式版发布 - 403频繁基本解决 - normal task基本完成 - +bili3.0主要更新(比较2.0) +1.对tasks和reqs均做了区分,不同的任务种类做不一样的事情。比如`tv_raffle_handler`,顾名思义,这个class里面就是处理小电视的东西 +2.tasks和reqs由原来的user成员函数变成了独立的各个静态函数,用户行为与用户尽量分离,同时减小了user这个实例对大小 +3.tasks的入口以及上下任务的连接设计。这里的task分两类,一种是真正的task,比如`tv_raffle_handler`,check->join->notify,构成了task执行链条,执行的下一个链条通过return的返回值控制,在notifier.py里的`__exec_one_step`具体执行,可以broadcast;另一种不是task,只是普通的函数,执行一次就够了,例如utils.py这些 +4.针对403问题,在web_session.py里面加了一个全局锁`sem = asyncio.Semaphore(3)`,控制流量大小,目前基本完全杜绝了403(晚高峰测试50用户,其中包括了节奏风暴暴力*2)。值得注意的是,如果数值过小比如1,那么就相当于一个单流量的了,那么延迟可能很高,你设置了3分钟后执行`tv_raffle_handler.join`,session可能5分钟后才排到队,发出网络请求;如果数值过高,那么可能就403了 +5.bili_cobsole对数据输入办法进行了控制,需要输入“指令序号+详细控制”一次性全部输入,例如“1 -u 0”,表示对用户0执行1号命令,具体什么控制这里可以看代码,一般用u表示用户index,p表示房间号码,n表示数量。默认的u是0 diff --git a/bili_console.py b/bili_console.py index 74d4696..64d6ed8 100644 --- a/bili_console.py +++ b/bili_console.py @@ -1,37 +1,44 @@ - -from connect import connect +import bili_statistics +import connect import printer import asyncio -from task import Messenger +import notifier from cmd import Cmd import getopt +from tasks.utils import UtilsTask +from tasks.custom import SendLatiaoTask, BuyLatiaoTask +from tasks.main_daily_job import JudgeCaseTask -class Biliconsole(Messenger, Cmd): +class Biliconsole(Cmd): + prompt = '' - def preloop(self): - Cmd.__init__(self) - self.prompt = '' - - def guide_of_console(self): - print('___________________________') - print('| 欢迎使用本控制台 |') - print('|1 输出本次用户统计 |') - print('|2 查看目前拥有礼物的统计 |') - print('|3 查看持有勋章状态 |') - print('|4 获取直播个人的基本信息 |') - print('|5 检查今日任务的完成情况 |') + def __init__(self, loop): + self.loop = loop + super().__init__() - print('|7 模拟电脑网页端发送弹幕 |') - print('|8 直播间的长短号码的转化 |') - print('|9 切换监听的直播间 |') - print('|10 T或F控制弹幕的开关 |') - print('|11 房间号码查看主播 |') - # print('|12 当前拥有的扭蛋币 |') - print('|12 开扭蛋币(只能1,10,100) |') - # print('|14 查看小黑屋的状态 |') - print('|15 检测参与正常的实物抽奖 |') - print('|16 赠指定总数的辣条到房间 |') + def guide_of_console(self): + print('____________________________') + print('| 欢迎使用本控制台       |') + print('|1 输出本次统计数据       |') + print('|2 查看目前拥有礼物的统计    |') + print('|3 查看持有勋章状态       |') + print('|4 检查主站今日任务的情况    |') + print('|5 检查直播分站今日任务的情况  |') + print('|6 获取主站个人的基本信息    |') + print('|7 获取直播分站个人的基本信息  |') + print('|8 检查风纪委今日自动投票的情况 |') + + print('|11当前拥有的扭蛋币       |') + print('|12开扭蛋币(一、十、百)    |') + print('|13直播间的长短号码的转化    |') + print('|14发送弹幕           |') + print('|15切换监听的直播间       |') + print('|16控制弹幕的开关        |') + + # print('|15 检测参与正常的实物抽奖 |') + print('|21赠指定总数的辣条到房间    |') + print('|22银瓜子全部购买辣条并送到房间 |') print(' ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄') def default(self, line): @@ -40,124 +47,146 @@ def default(self, line): def emptyline(self): self.guide_of_console() - def parse_line(self, line, key_wanted=None): - list_opt = getopt.getopt(line.split(), '-u:')[0] - if key_wanted is None: - return list_opt - value_wanted = None - for key, value in list_opt: - if key == key_wanted: - value_wanted = value - if key_wanted == '-u' and value_wanted is not None: - if value_wanted.isdigit(): - value_wanted = int(value_wanted) + # pattern = '-u:-p:' u(user_id):0,1…;n(num);p(point)指roomid(烂命名因为-r不合适) + def parse(self, arg, pattern, default_u=0): + args = arg.split() + try: + opts, args = getopt.getopt(args, pattern) + except getopt.GetoptError: + return [] + dict_results = {opt_name: opt_value for opt_name, opt_value in opts} + + opt_names = pattern.split(':')[:-1] + results = [] + for opt_name in opt_names: + opt_value = dict_results.get(opt_name) + if opt_name == '-u': + if opt_value is not None and opt_value.isdigit(): + results.append(int(opt_value)) + else: + results.append(default_u) + # -2是一个灾难性的东西 + # results.append(-2) + elif opt_name == '-n': + if opt_value is not None and opt_value.isdigit(): + results.append(int(opt_value)) + else: + results.append(0) + elif opt_name == '-p': + if opt_value is not None and opt_value.isdigit(): + room_id = int(opt_value) + else: + room_id = connect.get_default_roomid() + results.append(self.fetch_real_roomid(room_id)) else: - value_wanted = None - - print('list_opt', list_opt) - return value_wanted + results.append(opt_value) + return results - def do_1(self, line): - self.append2list_console([[], 'get_statistic', self.parse_line(line, '-u')]) + def do_1(self, arg): + id, = self.parse(arg, '-u:') + bili_statistics.print_statistics(id) - def do_2(self, line): - self.append2list_console([[], 'fetch_bag_list', self.parse_line(line, '-u')]) + def do_2(self, arg): + id, = self.parse(arg, '-u:') + self.exec_notifier_func_threads(id, UtilsTask.print_giftbags, []) - def do_3(self, line): - self.append2list_console([[], 'fetch_medal', self.parse_line(line, '-u')]) + def do_3(self, arg): + id, = self.parse(arg, '-u:') + self.exec_notifier_func_threads(id, UtilsTask.print_medals, []) - def do_4(self, line): - self.append2list_console([[], 'fetch_user_info', self.parse_line(line, '-u')]) + def do_4(self, arg): + id, = self.parse(arg, '-u:') + self.exec_notifier_func_threads(id, UtilsTask.print_bilimain_tasks, []) - def do_5(self, line): - self.append2list_console([[], 'check_taskinfo', self.parse_line(line, '-u')]) + def do_5(self, arg): + id, = self.parse(arg, '-u:') + self.exec_notifier_func_threads(id, UtilsTask.print_livebili_tasks, []) - def do_6(self, line): - self.append2list_console([[], 'TitleInfo', self.parse_line(line, '-u')]) - - def do_7(self, line): - msg = input('请输入要发送的信息:') - roomid = input('请输入要发送的房间号:') - real_roomid = self.fetch_real_roomid(roomid) - self.append2list_console([[msg, real_roomid], 'send_danmu_msg_web']) - - def do_8(self, line): - roomid = input('请输入要转化的房间号:') - if not roomid: - roomid = connect().room_id - self.append2list_console([[roomid], 'check_room', -1]) - - def do_9(self, line): - roomid = input('请输入roomid') - real_roomid = self.fetch_real_roomid(roomid) - self.append2list_console([[real_roomid], connect().reconnect]) - - def do_10(self, line): - new_words = input('弹幕控制') - if new_words == 'T': + def do_6(self, arg): + id, = self.parse(arg, '-u:') + self.exec_notifier_func_threads(id, UtilsTask.print_mainbili_userinfo, []) + + def do_7(self, arg): + id, = self.parse(arg, '-u:') + self.exec_notifier_func_threads(id, UtilsTask.print_livebili_userinfo, []) + + def do_8(self, arg): + id, = self.parse(arg, '-u:') + self.exec_notifier_func_threads(id, JudgeCaseTask.print_judge_tasks, []) + + def do_11(self, arg): + id, = self.parse(arg, '-u:') + self.exec_notifier_func_threads(id, UtilsTask.print_capsule_info, []) + + def do_12(self, arg): + id, num_opened = self.parse(arg, '-u:-n:') + self.exec_notifier_func_threads(id, UtilsTask.open_capsule, [num_opened]) + + def do_13(self, arg): + real_roomid, = self.parse(arg, '-p:') + self.exec_notifier_func_threads(-1, UtilsTask.get_real_roomid, [real_roomid]) + + def do_14(self, arg): + id, msg, real_roomid = self.parse(arg, '-u:-m:-p:') + self.exec_notifier_func_threads(id, UtilsTask.send_danmu, [msg, real_roomid]) + + def do_15(self, arg): + real_roomid, = self.parse(arg, '-p:') + self.exec_func_threads(connect.reconnect_danmu, [real_roomid]) + + def do_16(self, arg): + ctrl, = self.parse(arg, '-c:') + if ctrl == 'T': printer.control_printer(True) else: printer.control_printer(False) + + def do_21(self, arg): + real_roomid, num_max = self.parse(arg, '-p:-n:') + self.exec_task_threads(0, SendLatiaoTask, 0, [real_roomid, num_max]) + + def do_22(self, arg): + id, real_roomid = self.parse(arg, '-u:-p:') + self.exec_notifier_func_threads(id, BuyLatiaoTask.clean_latiao, [real_roomid]) - def do_11(self, line): - roomid = input('请输入roomid') - real_roomid = self.fetch_real_roomid(roomid) - self.append2list_console([[real_roomid], 'fetch_liveuser_info', -1]) - - def do_12(self, line): - count = input('请输入要开的扭蛋数目(1或10或100)') - self.append2list_console([[count], 'open_capsule']) - - def do_13(self, line): - roomid = input('请输入roomid') - real_roomid = self.fetch_real_roomid(roomid) - self.append2list_console([[real_roomid], 'watch_living_video', -1]) - - def do_15(self, line): - self.append2list_console([[], 'handle_1_room_substant', -1]) - - def do_16(self, line): - roomid = input('请输入roomid') - real_roomid = self.fetch_real_roomid(roomid) - num_wanted = int(input('请输入辣条数目')) - self.append2list_console([[real_roomid, num_wanted], self.send_latiao]) - - def append2list_console(self, request): - asyncio.run_coroutine_threadsafe(self.excute_async(request), self.loop) - - async def send_latiao(self, room_id, num_wanted): - i = 0 - while True: - num_wanted = await self.call('send_latiao', (room_id, num_wanted), i) - i += 1 - if num_wanted == 0: - break - await asyncio.sleep(1) - - def fetch_real_roomid(self, roomid): - if roomid: - real_roomid = [[roomid], 'check_room', -1] - else: - real_roomid = connect().room_id + def fetch_real_roomid(self, room_id): + real_roomid = [-1, UtilsTask.get_real_roomid, room_id] return real_roomid - async def excute_async(self, i): - print('bili_console:', i) - i.append(None) - if isinstance(i, list): - 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]) - i[0][j] = await self.call(i[0][j][1], i[0][j][0], i[0][j][2]) - if isinstance(i[1], str): - await self.call(i[1], i[0], i[2]) - else: - await i[1](*i[0]) - else: - print('qqqqqqqqqqqqqqqq', i) - await i() + # threads指thread safe + def exec_notifier_func_threads(self, *args): + asyncio.run_coroutine_threadsafe(self.exec_notifier_func(*args), self.loop) + def exec_func_threads(self, *args): + asyncio.run_coroutine_threadsafe(self.exec_func(*args), self.loop) + + def exec_task_threads(self, *args): + asyncio.run_coroutine_threadsafe(self.exec_task(*args), self.loop) + + # 这里args设置为list + async def exec_notifier_func(self, id, func, args): + # print('bili_console:', id, func, args) + for i, arg in enumerate(args): + if isinstance(arg, list): + args[i] = await notifier.exec_func(*arg) + # print('bili_console:', id, func, args) + await notifier.exec_func(id, func, *args) + + async def exec_func(self, func, args): + # print('bili_console:', func, args) + for i, arg in enumerate(args): + if isinstance(arg, list): + args[i] = await notifier.exec_func(*arg) + # print('bili_console:', func, args) + await func(*args) + + async def exec_task(self, id, task, step, args): + # print('bili_console:', task, args) + for i, arg in enumerate(args): + if isinstance(arg, list): + args[i] = await notifier.exec_func(*arg) + # print('bili_console:', task, args) + notifier.exec_task(id, task, step, *args) diff --git a/bili_global.py b/bili_global.py new file mode 100644 index 0000000..09178d7 --- /dev/null +++ b/bili_global.py @@ -0,0 +1,2 @@ +API_LIVE = 'https://api.live.bilibili.com' + diff --git a/bili_stats.py b/bili_statistics.py similarity index 69% rename from bili_stats.py rename to bili_statistics.py index 7828fe8..05de171 100644 --- a/bili_stats.py +++ b/bili_statistics.py @@ -1,4 +1,4 @@ -class BiliStats: +class BiliStatistics: def __init__(self, area_num=0): self.area_num = area_num # 只有一个(可以认为id为-1的super user) @@ -8,13 +8,16 @@ def __init__(self, area_num=0): self.joined_raffles = {} self.raffle_results = {} - def print_stats(self, id): + # 这是用于重复问题 + self.raffle_ids = [] + + def print_statistics(self, id): print('本次推送抽奖统计:') for k, v in self.pushed_raffles.items(): print(f'{v:^5} X {k}') print() - if id is None: + if id == -2: print('暂时不支持全部打印,考虑到用户可能很多') else: self.__print_one_stats(id) @@ -53,26 +56,45 @@ def add2results(self, gift_name, id, num=1): self.raffle_results[id] = {} results_of_id = self.raffle_results[id] results_of_id[gift_name] = results_of_id.get(gift_name, 0) + num + + # raffle_id int + def add2raffle_ids(self, raffle_id): + self.raffle_ids.append(raffle_id) + # 定期清理,防止炸掉 + if len(self.raffle_ids) > 150: + del self.raffle_ids[:75] + print(self.raffle_ids) + + def is_raffleid_duplicate(self, raffle_id): + return (raffle_id in self.raffle_ids) -var_bili_stats = BiliStats() +var = BiliStatistics() def init_area_num(area_num): - var_bili_stats.area_num = area_num + var.area_num = area_num def add2pushed_raffles(raffle_name, broadcast_type=0, num=1): - var_bili_stats.add2pushed_raffles(raffle_name, broadcast_type, int(num)) + var.add2pushed_raffles(raffle_name, broadcast_type, int(num)) def add2joined_raffles(raffle_name, id, num=1): - var_bili_stats.add2joined_raffles(raffle_name, id, int(num)) + var.add2joined_raffles(raffle_name, id, int(num)) def add2results(gift_name, id, num=1): - var_bili_stats.add2results(gift_name, id, int(num)) + var.add2results(gift_name, id, int(num)) + + +def add2raffle_ids(raffle_id): + var.add2raffle_ids(int(raffle_id)) + + +def is_raffleid_duplicate(raffle_id): + return var.is_raffleid_duplicate(int(raffle_id)) -def print_stats(id=None): - var_bili_stats.print_stats(id) +def print_statistics(id=None): + var.print_statistics(id) diff --git a/bili_user/base_user.py b/bili_user/base_user.py deleted file mode 100644 index c09b868..0000000 --- a/bili_user/base_user.py +++ /dev/null @@ -1,75 +0,0 @@ -import asyncio -from states import UserStates -import bili_stats -import printer -from config_loader import ConfigLoader - - -class BaseUser: - def __init__(self, user_id, dict_user, web_hub, task_control): - self.webhub = web_hub - self.user_id = user_id - self.user_name = dict_user['username'] - self.user_password = dict_user['password'] - self.task_control = task_control - self.state = UserStates(user_id, self.user_name) - - def printer_with_id(self, list_msg, tag_time=False): - list_msg[0] += f'(用户id:{self.user_id} 用户名:{self.user_name})' - printer.info(list_msg, tag_time) - - def write_user(self, dict_new): - self.webhub.set_status(dict_new) - ConfigLoader().write_user(dict_new, self.user_id) - - async def get_statistic(self): - await asyncio.sleep(0) - work_state, time_state = self.print_state() - self.printer_with_id([f'小黑屋状态: {work_state}'], True) - self.printer_with_id([f'工作状态: {time_state}'], True) - bili_stats.print_stats(self.user_id) - - async def online_request(self, func, *args): - rsp = await func(*args) - code = await self.state.check_log_state(func) - # print(rsp) - # 未登陆且未处理 - if rsp == 3 and code: - self.printer_with_id([f'判定出现了登陆失败,且未处理'], True) - self.state.logout() - # login - await self.handle_login_status() - # await asyncio.sleep(10) - print(self.state.delay_requests) - self.printer_with_id([f'已经登陆了'], True) - self.state.login() - rsp = await func(*args) - # 未登陆,但已处理 - elif not code: - self.printer_with_id([f'判定出现了登陆失败,已经处理'], True) - rsp = await func(*args) - return rsp - - async def update(self, func, values): - status = self.check_status(func, values) - if not status: - return await getattr(self, func)(*values) - - def go_to_bed(self): - self.state.go_to_bed() - - def wake_up(self): - self.state.wake_up() - - def fall_in_jail(self): - self.state.fall_in_jail() - self.printer_with_id([f'抽奖脚本检测{self.user_id}为小黑屋'], True) - - def out_of_jail(self): - self.state.out_of_jail() - - def print_state(self): - return self.state.print_state() - - def check_status(self, func, values): - return self.state.check_status(func, values) diff --git a/bili_user/daily_job_user.py b/bili_user/daily_job_user.py deleted file mode 100644 index 66ed601..0000000 --- a/bili_user/daily_job_user.py +++ /dev/null @@ -1,379 +0,0 @@ -import re -import json -import asyncio -import random -import utils -from bili_user.utils_user import UtilsUser -import printer -from task import Task - - -class DailyJobUser(UtilsUser): - async def heartbeat(self): - json_response = await self.online_request(self.webhub.apppost_heartbeat) - # print(json_response) - self.printer_with_id(['心跳包(5分钟左右间隔)'], True) - json_response = await self.online_request(self.webhub.pcpost_heartbeat) - # print(json_response) - return 260 - # print(json_response) - - async def fetch_heart_gift(self): - json_response = await self.online_request(self.webhub.heart_gift) - if json_response['code'] == 400: - self.fall_in_jail() - return 260 - - async def open_silver_box(self): - while True: - self.printer_with_id(["检查宝箱状态"], True) - temp = await self.online_request(self.webhub.get_time_about_silver) - # print (temp['code']) #宝箱领完返回的code为-10017 - if temp['code'] == -10017: - self.printer_with_id(["# 今日宝箱领取完毕"]) - json_rsp = None - else: - time_start = temp['data']['time_start'] - time_end = temp['data']['time_end'] - json_rsp = await self.online_request(self.webhub.get_silver, time_start, time_end) - if json_rsp is None or json_rsp['code'] == -10017 or json_rsp['code'] == -800: - sleeptime = (utils.seconds_until_tomorrow() + 300) - return sleeptime - break - # await asyncio.sleep(sleeptime) - elif not json_rsp['code']: - self.printer_with_id(["# 打开了宝箱"]) - elif json_rsp['code'] == 400: - self.printer_with_id(["# 宝箱开启中返回了小黑屋提示"]) - self.fall_in_jail() - return 0 - break - else: - self.printer_with_id(["# 继续等待宝箱冷却..."]) - # 未来如果取消了这个东西就睡眠185s,否则精确睡眠 - # surplus里面是min,float格式 - try: - sleeptime = (json_rsp['data'].get('surplus', 3)) * 60 + 5 - except: - sleeptime = 180 - print(json_rsp) - return sleeptime - break - - async def Daily_bag(self): - json_response = await self.online_request(self.webhub.get_dailybag) - # no done code - try: - for i in json_response['data']['bag_list']: - self.printer_with_id(["# 获得-" + i['bag_name'] + "-成功"]) - except: - print('hhhhhhjjjjdjdjdjddjdjdjjdjdjdjdjdjdjdjdjddjjddjjdjdjdjdj', json_response) - printer.warn(f'{json_response}') - return 21600 - - # 签到功能 - async def DoSign(self): - # -500 done - temp = await self.online_request(self.webhub.get_dosign) - self.printer_with_id([f'# 签到状态: {temp["msg"]}']) - if temp['code'] == -500 and '已' in temp['msg']: - sleeptime = (utils.seconds_until_tomorrow() + 300) - else: - sleeptime = 350 - return sleeptime - - # 领取每日任务奖励 - async def Daily_Task(self): - # -400 done/not yet - json_response2 = await self.online_request(self.webhub.get_dailytask) - self.printer_with_id([f'# 双端观看直播: {json_response2["msg"]}']) - if json_response2['code'] == -400 and '已' in json_response2['msg']: - sleeptime = (utils.seconds_until_tomorrow() + 300) - else: - sleeptime = 350 - return sleeptime - - async def Sign1Group(self, i1, i2): - json_response = await self.online_request(self.webhub.assign_group, i1, i2) - if not json_response['code']: - if json_response['data']['status']: - self.printer_with_id([f'# 应援团 {i1} 已应援过']) - else: - self.printer_with_id([f'# 应援团 {i1} 应援成功,获得 {json_response["data"]["add_num"]} 点亲密度']) - else: - self.printer_with_id([f'# 应援团 {i1} 应援失败']) - - # 应援团签到 - async def link_sign(self): - json_rsp = await self.online_request(self.webhub.get_grouplist) - list_check = json_rsp['data']['list'] - id_list = ((i['group_id'], i['owner_uid']) for i in list_check) - if list_check: - for (i1, i2) in id_list: - asyncio.ensure_future(self.Sign1Group(i1, i2)) - return 21600 - - async def send_latiao(self, room_id, num_wanted): - argvs = await self.fetch_bag_list(show=False) - sum = 0 - list_gift = [] - for i in argvs: - left_time = i[3] - gift_id = int(i[0]) - if (gift_id == 1) and (left_time is not None): - list_gift.append(i[:3]) - - for i in list_gift: - giftID = i[0] - giftNum = i[1] - if num_wanted - sum >= giftNum: - sum += int(giftNum) - bagID = i[2] - await self.send_gift_web(room_id, giftNum, bagID, giftID) - self.printer_with_id([f'送出{giftNum}个辣条'], True) - elif num_wanted - sum > 0: - giftNum = num_wanted - sum - sum += giftNum - bagID = i[2] - await self.send_gift_web(room_id, giftNum, bagID, giftID) - self.printer_with_id([f'送出{giftNum}个辣条'], True) - self.printer_with_id([f'一共送出{sum}个辣条'], True) - return num_wanted - sum - - async def send_expiring_gift(self): - if self.task_control['clean-expiring-gift']: - argvs = await self.fetch_bag_list(show=False) - roomID = self.task_control['clean-expiring-gift2room'] - time_set = self.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('发现即将过期的礼物') - if self.task_control['clean_expiring_gift2all_medal']: - print('正在投递其他勋章') - list_medal = await self.fetch_medal(show=False) - list_gift = await self.full_intimate(list_gift, list_medal) - - print('正在清理过期礼物到指定房间') - for i in list_gift: - giftID = i[0] - giftNum = i[1] - bagID = i[2] - await self.send_gift_web(roomID, giftNum, bagID, giftID) - else: - print('未发现即将过期的礼物') - return 21600 - - async def send_medal_gift(self): - list_medal = [] - if self.task_control['send2wearing-medal']: - list_medal = await self.WearingMedalInfo() - if not list_medal: - print('暂未佩戴任何勋章') - if self.task_control['send2medal']: - list_medal += await self.fetch_medal(False, self.task_control['send2medal']) - # print(list_medal) - print('正在投递勋章') - temp = await self.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 self.full_intimate(list_gift, list_medal) - return 21600 - - async def auto_send_gift(self): - await self.send_medal_gift() - await self.send_expiring_gift() - return 21600 - - async def full_intimate(self, list_gift, list_medal): - json_res = await self.online_request(self.webhub.gift_list) - dic_gift = {j['id']: (j['price'] / 100) for j in json_res['data']} - for roomid, left_intimate, medal_name in list_medal: - calculate = 0 - # print(list_gift) - for i in list_gift: - gift_id, gift_num, bag_id = i - # print(gift_id, bag_id) - if (gift_num * dic_gift[gift_id] <= left_intimate): - pass - elif left_intimate - dic_gift[gift_id] >= 0: - gift_num = int((left_intimate) / (dic_gift[gift_id])) - else: - continue - i[1] -= gift_num - score = dic_gift[gift_id] * gift_num - await asyncio.sleep(1.5) - await self.send_gift_web(roomid, gift_num, bag_id, gift_id) - calculate = calculate + score - left_intimate = left_intimate - score - self.printer_with_id([f'# 对{medal_name}共送出亲密度为{int(calculate)}的礼物']) - return [i for i in list_gift if i[1]] - - async def doublegain_coin2silver(self): - if self.task_control['doublegain_coin2silver']: - json_response0 = await self.online_request(self.webhub.doublegain_coin2silver) - json_response1 = await self.online_request(self.webhub.doublegain_coin2silver) - print(json_response0['msg'], json_response1['msg']) - return 21600 - - async def sliver2coin(self): - if self.task_control['silver2coin']: - # 403 done - # json_response1 = await self.online_request(self.webhub.silver2coin_app) - # -403 done - json_response = await self.online_request(self.webhub.silver2coin_web) - self.printer_with_id([f'# {json_response["msg"]}']) - # self.printer_with_id([f'# {json_response1["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) - return sleeptime - else: - return 350 - - return 21600 - - async def GetVideoExp(self, list_topvideo): - print('开始获取视频观看经验') - aid = random.choice(list_topvideo) - cid = await self.GetVideoCid(aid) - await self.online_request(self.webhub.Heartbeat, aid, cid) - - async def GiveCoinTask(self, coin_remain, list_topvideo): - while coin_remain > 0: - aid = random.choice(list_topvideo) - rsp = await self.GiveCoin2Av(aid, 1) - if rsp is None: - break - elif rsp: - coin_remain -= 1 - - async def GetVideoShareExp(self, list_topvideo): - print('开始获取视频分享经验') - aid = random.choice(list_topvideo) - await self.online_request(self.webhub.DailyVideoShare, aid) - - async def BiliMainTask(self): - login, watch_av, num, share_av = await self.GetRewardInfo() - if self.task_control['fetchrule'] == 'bilitop': - list_topvideo = await self.GetTopVideoList() - # print(list_topvideo) - else: - list_topvideo = await self.fetch_uper_video(self.task_control['mid']) - if (not login) or not watch_av: - await self.GetVideoExp(list_topvideo) - coin_sent = (num) / 10 - coin_set = min((self.task_control['givecoin']), 5) - coin_remain = coin_set - coin_sent - await self.GiveCoinTask(coin_remain, list_topvideo) - if not share_av: - await self.GetVideoShareExp(list_topvideo) - # b站傻逼有记录延迟,3点左右成功率高一点 - return utils.seconds_until_tomorrow() + 10800 - - async def check(self, id): - # 3放弃 - # 2 否 voterule - # 4 删除 votedelete - # 1 封杀 votebreak - text_rsp = await self.online_request(self.webhub.req_check_voted, id) - # print(response.text) - - pattern = re.compile(r'\((.+)\)') - match = pattern.findall(text_rsp) - temp = json.loads(match[0]) - # print(temp['data']['originUrl']) - data = temp['data'] - print(data['originContent']) - votebreak = data['voteBreak'] - voteDelete = data['voteDelete'] - voteRule = data['voteRule'] - status = data['status'] - voted = votebreak+voteDelete+voteRule - if voted: - percent = voteRule / voted - else: - percent = 0 - print('目前已投票', voted) - print('认为不违反规定的比例', percent) - vote = None - if voted >= 300: - if percent >= 0.75: - vote = 2 - elif percent <= 0.25: - vote = 4 - elif 0.4 <= percent <= 0.6: - vote = 2 - 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, status, voted - - async def judge(self): - num_case = 0 - num_voted = 0 - while True: - temp = await self.online_request(self.webhub.req_fetch_case) - if not temp['code']: - id = temp['data']['id'] - else: - print('本次未获取到案件') - # await asyncio.sleep(1) - break - num_case += 1 - while True: - vote, status, voted = await self.check(id) - if vote is None and status == 1: - if voted < 300: - printer.info([f'本次获取到的案件{id}暂时无法判定,在180s后重新尝试'], True) - await asyncio.sleep(180) - else: - printer.info([f'本次获取到的案件{id}暂时无法判定,在60s后重新尝试'], True) - await asyncio.sleep(60) - else: - break - if status != 1: - print('超时失败,请联系作者') - else: - print('投票决策', id, vote) - json_rsp = await self.online_request(self.webhub.req_vote_case, id, vote) - if not json_rsp['code']: - print(f'投票{id}成功') - num_voted += 1 - else: - print(f'投票{id}失败,请反馈作者') - - print('______________________________') - # await asyncio.sleep(1) - - self.printer_with_id([f'风纪委员会共获取{num_case}件案例,其中有效投票{num_voted}件'], True) - return 3600 - - async def daily_task(self, task_name): - time_delay = await getattr(self, task_name)() - time_delay += random.uniform(0, 30) - Task().call_after('daily_task', time_delay, (task_name,), self.user_id) diff --git a/bili_user/join_raffle_user.py b/bili_user/join_raffle_user.py deleted file mode 100644 index b86d55b..0000000 --- a/bili_user/join_raffle_user.py +++ /dev/null @@ -1,83 +0,0 @@ -from bili_user.base_user import BaseUser -import time -from task import Task -import bili_stats - - -class JoinRaffleUser(BaseUser): - async def handle_1_substantial_raffle(self, i, g): - json_response1 = await self.online_request(self.webhub.get_gift_of_lottery, i, g) - print("当前时间:", time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))) - print("参与实物抽奖回显:", json_response1) - - async def check_tv_result(self, raffleid, real_roomid): - json_response = await self.online_request(self.webhub.get_TV_result, real_roomid, raffleid) - # print(json_response) - if not json_response['code']: - # {'code': 0, 'msg': '正在抽奖中..', 'message': '正在抽奖中..', 'data': {'gift_id': '-1', 'gift_name': '', 'gift_num': 0, 'gift_from': '', 'gift_type': 0, 'gift_content': '', 'status': 3}} - if json_response['data']['gift_id'] == '-1': - print([f'json_response'], True) - return - elif json_response['data']['gift_id'] != '-1': - data = json_response['data'] - self.printer_with_id([f'# 房间{real_roomid:^9}小电视抽奖结果: {data["gift_name"]}X{data["gift_num"]}'], True) - bili_stats.add2results(data['gift_name'], self.user_id, data['gift_num']) - - async def handle_1_TV_raffle(self, real_roomid, raffleid, raffle_type): - print('参与', raffleid) - json_response2 = await self.online_request(self.webhub.get_gift_of_TV, real_roomid, raffleid) - bili_stats.add2joined_raffles('小电视(合计)', self.user_id) - self.printer_with_id([f'参与了房间{real_roomid:^9}的小电视抽奖'], True) - self.printer_with_id([f'# 小电视抽奖状态: {json_response2["msg"]}']) - # -400不存在 - # -500繁忙 - code = json_response2['code'] - if not code: - Task().call_after('check_tv_result', 190, (raffleid, real_roomid), id=self.user_id) - return True - elif code == -500: - print('# -500繁忙,稍后重试') - return False - elif code == 400: - self.fall_in_jail() - return False - else: - print(json_response2) - return True - - async def handle_1_guard_raffle(self, roomid, raffleid): - json_response2 = await self.online_request(self.webhub.get_gift_of_guard, roomid, raffleid) - self.printer_with_id([f'参与了房间{roomid:^9}的大航海抽奖'], True) - if not json_response2['code']: - self.printer_with_id([f'# 房间{roomid:^9}大航海抽奖结果: {json_response2["data"]["message"]}']) - bili_stats.add2joined_raffles('大航海(合计)', self.user_id) - else: - print(json_response2) - return True - - async def handle_1_activity_raffle(self, room_id, text2, raffleid): - # print('参与') - json_response1 = await self.online_request(self.webhub.get_gift_of_events_app, room_id, text2, raffleid) - json_pc_response = await self.online_request(self.webhub.get_gift_of_events_web, room_id, text2, raffleid) - - self.printer_with_id([f'参与了房间{room_id:^9}的活动抽奖'], True) - - if not json_response1['code']: - self.printer_with_id([f'# 移动端活动抽奖结果: {json_response1["data"]["gift_desc"]}']) - gift_name, gift_num = json_response1['data']['gift_desc'].split('X') - bili_stats.add2results(gift_name, self.user_id, gift_num) - else: - print(json_response1) - self.printer_with_id([f'# 移动端活动抽奖结果: {json_response1}']) - - self.printer_with_id( - [f'# 网页端活动抽奖状态: {json_pc_response}']) - if not json_pc_response['code']: - bili_stats.add2joined_raffles('活动(合计)', self.user_id) - else: - print(json_pc_response) - return True - - async def post_watching_history(self, roomid): - await self.online_request(self.webhub.post_watching_history, roomid) - diff --git a/bili_user/login_user.py b/bili_user/login_user.py deleted file mode 100644 index 1111922..0000000 --- a/bili_user/login_user.py +++ /dev/null @@ -1,106 +0,0 @@ -import rsa -import base64 -from urllib import parse -from bili_user.base_user import BaseUser - - -class LoginUser(BaseUser): - async def handle_login_status(self): - if not self.webhub.cookie_existed(): - return await self.login() - if not (await self.check_token()): - if not (await self.refresh_token()): - return await self.login() - else: - if not (await self.check_token()): - print('请联系作者!!!!!!!!!') - return await self.login() - return True - - async def check_token(self): - json_response = await self.webhub.check_token() - if not json_response['code'] and 'mid' in json_response['data']: - print('token有效期检查: 仍有效') - # print(json_response) - return True - print('token可能过期', json_response) - return False - - async def refresh_token(self): - json_response = await self.webhub.refresh_token() - - # 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 - } - self.write_user(dic_saved_session) - # 更新token信息 - return True - return False - - async def login(self): - username = self.user_name - password = self.user_password - json_rsp = await self.webhub.fetch_key() - value = json_rsp['data'] - key = value['key'] - Hash = str(value['hash']) - pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(key.encode()) - hashed_password = base64.b64encode(rsa.encrypt((Hash + password).encode('utf-8'), pubkey)) - url_password = parse.quote_plus(hashed_password) - url_username = parse.quote_plus(username) - - json_rsp = await self.webhub.normal_login(url_username, url_password) - # print(json_rsp) - - while json_rsp['code'] == -105: - json_rsp = await self.webhub.captcha_login(url_username, url_password) - # print(json_rsp) - - # 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) - - self.write_user(dic_saved_session) - self.printer_with_id(['登陆成功'], True) - return True - - else: - dic_saved_session = { - 'csrf': f'{json_rsp}', - 'access_key': '', - 'refresh_token': '', - 'cookie': '', - 'uid': 'NULL' - } - # print(dic_saved_session) - - self.write_user(dic_saved_session) - self.printer_with_id([f'登录失败,错误信息为:{json_rsp}'], True) - return False - diff --git a/bili_user/super_user.py b/bili_user/super_user.py deleted file mode 100644 index a8b3f8b..0000000 --- a/bili_user/super_user.py +++ /dev/null @@ -1,310 +0,0 @@ -from task import Task -import asyncio -import random -import printer -import webbrowser -from PIL import Image -from io import BytesIO -import re -import time - - -def CurrentTime(): - # currenttime = int(time.mktime(datetime.datetime.now().timetuple())) - return int(time.time()) - - -class SuperUser(): - - def __init__(self, webhub): - self.webhub = webhub - self.user_id = -1 - self.list_raffle_id = [] - - 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 check_room_state(self, roomid): - json_rsp = await self.webhub.req_room_init(roomid) - return json_rsp['data']['live_status'] - - async def get_one(self, areaid): - # 1 娱乐分区, 2 游戏分区, 3 手游分区, 4 绘画分区 - if areaid == 1: - roomid = 23058 - state = await self.check_room_state(roomid) - if state == 1: - printer.info([f'{areaid}号弹幕监控选择房间({roomid})'], True) - return roomid - - while True: - json_rsp = await self.webhub.req_realroomid(areaid) - data = json_rsp['data'] - roomid = random.choice(data)['roomid'] - state = await self.check_room_state(roomid) - if state == 1: - printer.info([f'{areaid}号弹幕监控选择房间({roomid})'], True) - return roomid - - async def check_room_for_danmu(self, room_id, area_id): - json_response = await self.webhub.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 self.webhub.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 - - async def find_live_user_roomid(self, wanted_name): - print('发现名字', wanted_name) - for i in range(len(wanted_name), 0, -1): - json_rsp = await self.webhub.search_biliuser(wanted_name[:i]) - results = json_rsp['result'] - if results is None: - # print('屏蔽全名') - continue - for i in results: - real_name = re.sub(r'<[^>]*>', '', i['uname']) - # print('去除干扰', real_name) - if real_name == wanted_name: - print('找到结果', i['room_id']) - return i['room_id'] - # print('结束一次') - - print('第2备份启用') - for i in range(len(wanted_name)): - json_rsp = await self.webhub.search_biliuser(wanted_name[i:]) - results = json_rsp['result'] - if results is None: - # print('屏蔽全名') - continue - for i in results: - real_name = re.sub(r'<[^>]*>', '', i['uname']) - # print('去除干扰', real_name) - if real_name == wanted_name: - print('找到结果', i['room_id']) - return i['room_id'] - - print('第3备份启用') - for i in range(len(wanted_name), 0, -1): - json_rsp = await self.webhub.search_liveuser(wanted_name[:i]) - results = json_rsp['result'] - if results is None: - # print('屏蔽全名') - continue - for i in results: - real_name = re.sub(r'<[^>]*>', '', i['uname']) - # print('去除干扰', real_name) - if real_name == wanted_name: - print('找到结果', i['roomid']) - return i['roomid'] - - print('第4备份启用') - for i in range(len(wanted_name)): - json_rsp = await self.webhub.search_liveuser(wanted_name[i:]) - results = json_rsp['result'] - if results is None: - # print('屏蔽全名') - continue - for i in results: - real_name = re.sub(r'<[^>]*>', '', i['uname']) - # print('去除干扰', real_name) - if real_name == wanted_name: - print('找到结果', i['roomid']) - return i['roomid'] - - async def check_room(self, roomid): - json_response = await self.webhub.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 fetch_liveuser_info(self, real_roomid): - json_response = await self.webhub.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 self.webhub.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 self.webhub.load_img(data['info']['face']) - img = Image.open(BytesIO(await response_face.read())) - img.thumbnail(size) - try: - img.show() - except: - pass - - async def watch_living_video(self, cid): - import sound - sound.set_honors_silent_switch(False) - sound.set_volume(1) - sound.play_effect('piano:D3') - json_response = await self.webhub.playurl(cid) - print(json_response) - if not json_response['code']: - data = json_response['data'] - print(data) - webbrowser.open(data) - - async def check_if_normal_room(self, roomid): - json_response = await self.webhub.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) - return False - else: - printer.info([f'抽奖脚本检测到房间{roomid:^9}为正常房间'], True) - return True - - # 与弹幕抽奖对应,这里的i其实是抽奖id - async def handle_1_room_substant(self): - list_available_raffleid = [] - blacklist = ['test', 'TEST', '测试', '加密'] - max = 10000 - min = 50 - while max > min: - # print(min, max) - middle = int((min + max + 1) / 2) - code_middle = (await self.webhub.get_lotterylist(middle))['code'] - if code_middle: - code_middle1 = (await self.webhub.get_lotterylist(middle + 1))['code'] - code_middle2 = (await self.webhub.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 self.webhub.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): - print('本次获取到的抽奖id为', i, g) - list_available_raffleid.append((i, g), 100) - - for tuple_values, max_wait in list_available_raffleid: - Task().call_after('handle_1_substantial_raffle', 0, tuple_values, time_range=max_wait) - - async def handle_1_room_activity(self, room_id, text2): - result = True - if result: - json_response = await self.webhub.get_giftlist_of_events(room_id) - checklen = json_response['data'] - list_available_raffleid = [] - for j in checklen: - # await asyncio.sleep(random.uniform(0.5, 1)) - # resttime = j['time'] - raffleid = j['raffleId'] - # if self.statistics.check_activitylist(text1, raffleid): - # list_available_raffleid.append(raffleid) - list_available_raffleid.append((room_id, text2, raffleid), 00000) - for tuple_values, max_wait in list_available_raffleid: - Task().call_after('handle_1_activity_raffle', 0, tuple_values, time_range=max_wait) - - async def handle_1_room_TV(self, real_roomid): - json_response = await self.webhub.get_giftlist_of_TV(real_roomid) - # 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'] - max_wait = j['time'] - 10 - # 处理一些重复 - if not self.check_duplicate(raffle_id): - print('本次获取到的抽奖id为', raffle_id) - list_available_raffleid.append(((real_roomid, raffle_id, raffle_type), max_wait)) - self.add2raffle_id(raffle_id) - - # print(list_available_raffleid) - for tuple_values, max_wait in list_available_raffleid: - Task().call_after('handle_1_TV_raffle', 0, tuple_values, time_range=max_wait) - - async def handle_1_room_guard(self, roomid, raffleid=None): - if raffleid is not None: - json_response1 = {'data': [{'id': raffleid, 'time': 65}]} - else: - while True: - json_response1 = await self.webhub.get_giftlist_of_guard(roomid) - print(json_response1) - if json_response1['data']: - break - await asyncio.sleep(1) - if not json_response1['data']: - print(f'{roomid}没有guard或者guard已经领取') - return - list_available_raffleid = [] - # guard这里领取后,list对应会消失,其实就没有status了,这里是为了统一 - for j in json_response1['data']: - id = j['id'] - # 总督长达一天,额外处理 - max_wait = min(j['time'] - 10, 240) - if not self.check_duplicate(id): - self.add2raffle_id(id) - list_available_raffleid.append(((roomid, id), max_wait)) - - for tuple_values, max_wait in list_available_raffleid: - Task().call_after('handle_1_guard_raffle', 0, tuple_values, time_range=max_wait) - - async def update(self, func, value): - return (await getattr(self, func)(*value)) - - - - - diff --git a/bili_user/user.py b/bili_user/user.py deleted file mode 100644 index 2e2eb4c..0000000 --- a/bili_user/user.py +++ /dev/null @@ -1,8 +0,0 @@ -from bili_user.daily_job_user import DailyJobUser -from bili_user.join_raffle_user import JoinRaffleUser -from bili_user.login_user import LoginUser - - -class User(DailyJobUser, JoinRaffleUser, LoginUser): - pass - diff --git a/bili_user/utils_user.py b/bili_user/utils_user.py deleted file mode 100644 index 66bcfc4..0000000 --- a/bili_user/utils_user.py +++ /dev/null @@ -1,356 +0,0 @@ -import time -import re -from operator import itemgetter -from io import BytesIO -from PIL import Image -from bili_user.base_user import BaseUser -import utils - - -class UtilsUser(BaseUser): - async def fetch_capsule_info(self): - json_response = await self.online_request(self.webhub.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(self, count): - json_response = await self.online_request(self.webhub.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 fetch_user_info(self): - json_response = await self.online_request(self.webhub.fetch_user_info) - json_response_ios = await self.online_request(self.webhub.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 - binary_body = await self.online_request(self.webhub.load_img, userInfo['face']) - img = Image.open(BytesIO(binary_body)) - 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(self, verbose=False, bagid=None, show=True): - json_response = await self.online_request(self.webhub.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(self): - json_response = await self.online_request(self.webhub.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(self, roomid): - json_response = await self.online_request(self.webhub.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(self, roomid, num_wanted, bagid, giftid=None): - if giftid is None: - giftid, num_owned = await self.fetch_bag_list(False, bagid) - num_wanted = min(num_owned, num_wanted) - json_response = await self.online_request(self.webhub.check_room, roomid) - ruid = json_response['data']['uid'] - biz_id = json_response['data']['room_id'] - # 200027 不足数目 - json_response1 = await self.online_request(self.webhub.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']) - - async def fetch_liveuser_info(self, real_roomid): - json_response = await self.online_request(self.webhub.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 self.online_request(self.webhub.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 self.online_request(self.webhub.load_img, data['info']['face']) - img = Image.open(BytesIO(await response_face.read())) - img.thumbnail(size) - try: - img.show() - except: - pass - - async def GiveCoin2Av(self, video_id, num): - if num not in (1, 2): - return False - # 10004 稿件已经被删除 - # 34005 超过,满了 - # -104 不足硬币 - json_rsp = await self.online_request(self.webhub.ReqGiveCoin2Av, video_id, num) - code = json_rsp['code'] - if not code: - print(f'给视频av{video_id}投{num}枚硬币成功') - return True - else: - print('投币失败', json_rsp) - if code == -104 or code == -102: - return None - return False - - async def GetTopVideoList(self): - text_rsp = await self.online_request(self.webhub.req_fetch_av) - # print(text_rsp) - 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(self, list_mid): - list_av = [] - for mid in list_mid: - json_rsp = await self.online_request(self.webhub.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 self.online_request(self.webhub.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(self, video_aid): - json_rsp = await self.online_request(self.webhub.ReqVideoCid, video_aid) - # print(json_rsp[0]['cid']) - return (json_rsp[0]['cid']) - - async def GetRewardInfo(self, show=True): - json_rsp = await self.online_request(self.webhub.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 WearingMedalInfo(self): - json_response = await self.online_request(self.webhub.ReqWearingMedal) - if not json_response['code']: - data = json_response['data'] - if data: - return [(data['roominfo']['room_id'], int(data['day_limit']) - int(data['today_feed']), data['medal_name']), ] - else: - # print('暂无佩戴任何勋章') - return [] - - # web api返回值信息少 - - async def TitleInfo(self): - json_response = await self.online_request(self.webhub.ReqTitleInfo) - # 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(i['activity'], i['score'], max) - - async def fetch_medal(self, show=True, list_wanted_medal=None): - printlist = [] - list_medal = [] - if show: - printlist.append('查询勋章信息') - printlist.append( - '{} {} {:^12} {:^10} {} {:^6} '.format(utils. adjust_for_chinese('勋章'), utils. adjust_for_chinese('主播昵称'), '亲密度', - '今日的亲密度', utils. adjust_for_chinese('排名'), '勋章状态')) - dic_worn = {'1': '正在佩戴', '0': '待机状态'} - json_response = await self.online_request(self.webhub.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} '.format(utils. adjust_for_chinese(i['medal_name'] + '|' + str(i['level'])), - utils. adjust_for_chinese(i['anchorInfo']['uname']), - str(i['intimacy']) + '/' + str(i['next_intimacy']), - str(i['todayFeed']) + '/' + str(i['dayLimit']), - utils. adjust_for_chinese(str(i['rank'])), - dic_worn[str(i['status'])])) - if show: - self.printer_with_id(printlist, True) - if list_wanted_medal: - 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(self, msg, roomId): - json_response = await self.online_request(self.webhub.send_danmu_msg_web, msg, roomId) - print(json_response) diff --git a/bug b/bug new file mode 100644 index 0000000..33c1936 --- /dev/null +++ b/bug @@ -0,0 +1,10 @@ + None https://www.bilibili.com/widget/getPageList?aid=41272272 +404返回 妈的sbb站 + +存在一个可能卡死的地方,但是到现在都找不到,不确定是否与上面的重复 + +41272272 +输入数目1 +give_coin +{'code': 10003, 'message': '不存在该稿件', 'ttl': 1, 'data': {'like': False}} + diff --git a/cdn.py b/cdn.py deleted file mode 100644 index d305346..0000000 --- a/cdn.py +++ /dev/null @@ -1,47 +0,0 @@ -import asyncio -import random -import aiohttp - - -class Host(): - instance = None - - def __new__(cls, ips=None): - if not cls.instance: - cls.instance = super(Host, cls).__new__(cls) - cls.instance.list_ips = ips - - return cls.instance - - async def test_proxy(self, ip): - url = f'http://{ip}/room/v1/Room/room_init?id=6' - # url = f'http://{ip}/gift/v3/live/gift_config' - headers = {'host': 'api.live.bilibili.com'} - timeout = aiohttp.ClientTimeout(total=3) - async with aiohttp.ClientSession(timeout=timeout) as session: - num_won = 0 - for i in range(10): - try: - rsp = await session.get(url, headers=headers) - if rsp.status == 200: - num_won += 1 - except: - print('fail ip', ip) - if num_won >= 9: - return True - return False - - async def proxies_filter(self): - tasklist = [] - for ip in self.list_ips: - task = asyncio.ensure_future(self.test_proxy(ip)) - tasklist.append(task) - results = await asyncio.gather(*tasklist) - self.list_ips = list(set([ip for ip, tag in zip(self.list_ips, results) if tag])) - self.list_ips.sort() - print('可用ip为', len(self.list_ips), '个') - - def get_host(self): - return random.choice(self.list_ips) - - diff --git a/config/bili.toml b/conf/bili.toml similarity index 100% rename from config/bili.toml rename to conf/bili.toml diff --git a/config/color.toml b/conf/color.toml similarity index 100% rename from config/color.toml rename to conf/color.toml diff --git a/config/user.toml b/conf/user.toml similarity index 62% rename from config/user.toml rename to conf/user.toml index 1b4c248..7ef5aa3 100644 --- a/config/user.toml +++ b/conf/user.toml @@ -7,34 +7,23 @@ csrf = "" uid = "" refresh_token = "" -[[users]] -username = "" -password = "" -access_key = "" -cookie = "" -csrf = "" -uid = "" -refresh_token = "" - -[platform] -platform = "ios_pythonista" - [print_control] danmu = false [task_control] clean-expiring-gift = false -set-expiring-time = 43200 +set-expiring-time = 0 clean_expiring_gift2all_medal = false clean-expiring-gift2room = 0 silver2coin = false -send2wearing-medal = false +send2wearing-medal = true send2medal = [] doublegain_coin2silver = false -givecoin = 0 +givecoin = 5 fetchrule = "bilitop" mid = [ 207539637,] [other_control] default_monitor_roomid = 23058 -raffle_minitor_roomid = 0 +raffle_minitor_roomid = 1823260 +area_ids = [ 1, 2, 3, 4, 5,] diff --git a/conf_loader.py b/conf_loader.py new file mode 100644 index 0000000..6604d7a --- /dev/null +++ b/conf_loader.py @@ -0,0 +1,86 @@ +import toml + + +# "#969696" +def hex_to_rgb_percent(str_hex): + return tuple(int(n, 16)/255 for n in (str_hex[1:3], str_hex[3:5], str_hex[5:7])) + + +# [255 255 255] +def rgb_to_percent(list_rgb): + return list_rgb[0]/255, list_rgb[1]/255, list_rgb[2]/255 + + +class ConfLoader(): + def set_path(self, file_color, file_user, file_bili): + self.file_color = file_color + self.file_user = file_user + self.file_bili = file_bili + + ''' + self.dict_color = self.read_color() + print(self.dict_color) + + self.dict_user = self.read_user() + print(self.dict_user) + + self.dict_bili = self.read_bili() + print(self.dict_bili) + print("# 初始化完成") + ''' + + def write_user(self, dict_new, user_id): + with open(self.file_user, encoding="utf-8") as f: + dict_user = toml.load(f) + for i, value in dict_new.items(): + dict_user['users'][user_id][i] = value + with open(self.file_user, 'w', encoding="utf-8") as f: + toml.dump(dict_user, f) + + def read_bili(self): + with open(self.file_bili, encoding="utf-8") as f: + dict_bili = toml.load(f) + return dict_bili + + def read_color(self): + with open(self.file_color, encoding="utf-8") as f: + dict_color = toml.load(f) + for i in dict_color.values(): + for key, color in i.items(): + if isinstance(color, str): + i[key] = hex_to_rgb_percent(color) + elif isinstance(color, list): + i[key] = rgb_to_percent(color) + + return dict_color + + def read_user(self): + with open(self.file_user, encoding="utf-8") as f: + dict_user = toml.load(f) + return dict_user + + +var = ConfLoader() + + +def set_path(root_path): + file_color = f'{root_path}/conf/color.toml' + file_user = f'{root_path}/conf/user.toml' + file_bili = f'{root_path}/conf/bili.toml' + var.set_path(file_color, file_user, file_bili) + + +def write_user(dict_new, user_id): + var.write_user(dict_new, user_id) + + +def read_bili(): + return var.read_bili() + + +def read_color(): + return var.read_color() + + +def read_user(): + return var.read_user() diff --git a/config/ips.toml b/config/ips.toml deleted file mode 100644 index 4a251a5..0000000 --- a/config/ips.toml +++ /dev/null @@ -1,68 +0,0 @@ -list_ips = [ - '111.1.27.34', - '111.1.27.35', - '111.1.27.36', - '111.19.137.162', - '111.19.137.163', - '111.19.137.164', - '111.230.84.45', - '111.230.84.59', - '111.230.85.89', - '111.231.211.246', - '111.231.212.88', - '111.47.237.18', - '111.6.174.4', - '111.62.72.10', - '111.62.72.8', - '111.62.72.9', - '112.16.2.205', - '112.16.2.206', - '112.16.2.207', - '114.80.223.170', - '114.80.223.171', - '114.80.223.172', - '114.80.223.175', - '114.80.223.176', - '114.80.223.177', - '117.161.12.114', - '117.161.12.115', - '117.161.12.116', - '118.89.74.220', - '118.89.74.45', - '120.192.82.104', - '120.192.82.105', - '120.192.82.106', - '120.92.113.211', - '120.92.113.99', - '120.92.174.135', - '120.92.218.109', - '120.92.218.164', - '120.92.78.97', - '122.143.15.150', - '122.228.77.80', - '122.228.77.81', - '122.228.77.82', - '122.228.77.83', - '122.228.77.84', - '122.228.77.85', - '123.206.1.201', - '140.143.177.142', - '140.143.82.138', - '211.159.214.11', - '218.98.33.195', - '218.98.33.196', - '218.98.33.197', - '221.13.201.7', - '221.13.201.8', - '221.13.201.9', - '222.186.35.79', - '222.186.35.80', - '222.186.35.81', - '223.85.58.74', - '58.222.35.200', - '58.222.35.201', - '58.222.35.202', - '58.222.35.203', - '58.222.35.204', - '58.222.35.205', - ] diff --git a/config_loader.py b/config_loader.py deleted file mode 100644 index 7a737e3..0000000 --- a/config_loader.py +++ /dev/null @@ -1,76 +0,0 @@ -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(): - - inst = None - - def __new__(cls, file_color=None, file_user=None, file_bili=None, file_ip=None): - if not cls.inst: - cls.inst = super(ConfigLoader, cls).__new__(cls) - cls.inst.file_color = file_color - # cls.inst.dict_color = cls.inst.read_color() - # print(cls.inst.dict_color) - - cls.inst.file_user = file_user - # cls.inst.dict_user = cls.inst.read_user() - # print(cls.inst.dict_user) - - cls.inst.file_bili = file_bili - # cls.inst.dict_bili = cls.inst.read_bili() - # print(cls.inst.dict_bili) - # print("# 初始化完成") - - cls.inst.file_ip = file_ip - # cls.inst.dict_ip = cls.inst.read_ip() - # print(cls.inst.dict_ip) - return cls.inst - - def write_user(self, dict_new, user_id): - with open(self.file_user, encoding="utf-8") as f: - dict_user = toml.load(f) - for i, value in dict_new.items(): - dict_user['users'][user_id][i] = value - with open(self.file_user, 'w', encoding="utf-8") as f: - toml.dump(dict_user, f) - - def read_bili(self): - with open(self.file_bili, encoding="utf-8") as f: - dict_bili = toml.load(f) - return dict_bili - - def read_ip(self): - with open(self.file_ip, encoding="utf-8") as f: - dict_ip = toml.load(f) - return dict_ip - - def read_color(self): - with open(self.file_color, encoding="utf-8") as f: - dict_color = toml.load(f) - for i in dict_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 dict_color - - def read_user(self): - with open(self.file_user, encoding="utf-8") as f: - dict_user = toml.load(f) - return dict_user - - - - diff --git a/connect.py b/connect.py index b85105c..b8d9820 100644 --- a/connect.py +++ b/connect.py @@ -9,17 +9,11 @@ def CurrentTime(): return currenttime -class connect(): - __slots__ = ('danmuji', 'room_id', 'area_id') - instance = None - - def __new__(cls, room_id=None): - if not cls.instance: - cls.instance = super(connect, cls).__new__(cls) - cls.instance.danmuji = None - cls.instance.room_id = room_id - cls.instance.area_id = -1 - return cls.instance +class DanmuConnect(): + def __init__(self, room_id): + self.danmuji = None + self.room_id = room_id + self.area_id = -1 async def run(self): self.danmuji = danmu.DanmuPrinter(self.room_id, self.area_id) @@ -47,6 +41,7 @@ async def run(self): async def reconnect(self, room_id): self.room_id = room_id print('已经切换room_id') + # 其实这里仍然不够安全,如果在未初始化完毕的时候调用,还是会出错误 if self.danmuji is not None: self.danmuji.room_id = room_id await self.danmuji.close() @@ -118,7 +113,21 @@ async def run(self): await asyncio.wait(pending) printer.info(['Yj弹幕姬退出,剩余任务处理完毕'], True) - - - +var_danmu_connect = DanmuConnect(0) + + +def init_danmu_roomid(real_roomid): + var_danmu_connect.room_id = real_roomid + + +async def reconnect_danmu(real_roomid): + await var_danmu_connect.reconnect(real_roomid) + + +def get_default_roomid(): + return var_danmu_connect.room_id + + +async def run_danmu(): + await var_danmu_connect.run() diff --git a/danmu.py b/danmu.py index de9df24..d8ff031 100644 --- a/danmu.py +++ b/danmu.py @@ -1,12 +1,16 @@ import printer -from task import RaffleHandler -from task import Task +import notifier +import bili_statistics +from tasks.tv_raffle_handler import TvRaffleHandlerTask +from tasks.guard_raffle_handler import GuardRaffleHandlerTask +from tasks.storm_raffle_handler import StormRaffleHandlerTask +from tasks.utils import UtilsTask +import raffle_handler import asyncio import aiohttp import struct import json import sys -import bili_stats class BaseDanmu(): @@ -142,13 +146,13 @@ def handle_danmu(self, body): class DanmuRaffleHandler(BaseDanmu): async def reset_roomid(self): - x = await Task().call('get_one', (self._area_id,), -1) + x = await notifier.exec_func(-1, UtilsTask.get_room_by_area, self._area_id) self.room_id = x async def check_area(self): try: while True: - is_ok = await asyncio.shield(Task().call('check_room_for_danmu', (self._room_id, self._area_id), -1)) + is_ok = await asyncio.shield(notifier.exec_func(-1, UtilsTask.is_ok_as_monitor, self._room_id, self._area_id)) if not is_ok: printer.info([f'{self._room_id}不再适合作为监控房间,即将切换'], True) return @@ -187,20 +191,20 @@ def handle_danmu(self, body): raffle_name = str_gift broadcast = msg_common.split('广播')[0] printer.info([f'{self._area_id}号弹幕监控检测到{real_roomid:^9}的{raffle_name}'], True) - RaffleHandler().push2queue((real_roomid,), 'handle_TV_raffle') + raffle_handler.push2queue(TvRaffleHandlerTask, real_roomid) broadcast_type = 0 if broadcast == '全区' else 1 - bili_stats.add2pushed_raffles(raffle_name, broadcast_type) + bili_statistics.add2pushed_raffles(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().push2queue((real_roomid,), 'handle_guard_raffle') + raffle_handler.push2queue(GuardRaffleHandlerTask, real_roomid) broadcast_type = 0 if raffle_name == '总督' else 2 - bili_stats.add2pushed_raffles(raffle_name, broadcast_type) + bili_statistics.add2pushed_raffles(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) - bili_stats.add2pushed_raffles(raffle_name) + bili_statistics.add2pushed_raffles(raffle_name) return True @@ -256,19 +260,23 @@ def handle_danmu(self, body): 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: + raffle_id = id + printer.info([f'{self._area_id}号弹幕监控检测到{"0":^9}的节奏风暴(id: {raffle_id})'], True) + # raffle_handler.exec_at_once(StormRaffleHandlerTask, 0, raffle_id) + bili_statistics.add2pushed_raffles('Yj协同节奏风暴', 2) 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 + type, raffle_id, real_roomid = result if type == '+': - printer.info([f'{self._area_id}号弹幕监控检测到{room_id:^9}的大航海(id: {raffle_id})'], True) - RaffleHandler().push2queue((room_id, raffle_id), 'handle_guard_raffle') - bili_stats.add2pushed_raffles('Yj协同大航海', 2) + printer.info([f'{self._area_id}号弹幕监控检测到{real_roomid:^9}的大航海(id: {raffle_id})'], True) + raffle_handler.push2queue(GuardRaffleHandlerTask, real_roomid, raffle_id) + bili_statistics.add2pushed_raffles('Yj协同大航海', 2) except Exception: printer.warn(f'Yj监控房间内可能有恶意干扰{uid}: {ori}') return True diff --git a/main.py b/main.py deleted file mode 100644 index e69de29..0000000 diff --git a/monitor_substance_raffle.py b/monitor_substance_raffle.py new file mode 100644 index 0000000..e5a55ee --- /dev/null +++ b/monitor_substance_raffle.py @@ -0,0 +1,66 @@ +import asyncio +import notifier +from tasks.substance_raffle_handler import SubstanceRaffleHandlerTask + + +class SubstanceRaffleMonitor: + def __init__(self): + self.curr_aid = None + + async def init_curr_aid(self): + max_aid = 1000 + min_aid = 50 + while max_aid > min_aid: + print(min_aid, max_aid) + mid_aid = int((min_aid + max_aid + 1) / 2) + code_mid = await notifier.exec_func(-1, SubstanceRaffleHandlerTask.check_code, mid_aid) + if code_mid: + code_mid1 = await notifier.exec_func(-1, SubstanceRaffleHandlerTask.check_code, mid_aid+1) + code_mid2 = await notifier.exec_func(-1, SubstanceRaffleHandlerTask.check_code, mid_aid+2) + if code_mid1 and code_mid2: + max_aid = mid_aid - 1 + else: + min_aid = mid_aid + 1 + else: + min_aid = mid_aid + print('最新实物抽奖id为', min_aid, max_aid) + # 经过验证过,还是以防万一,防止翻车 + assert min_aid == max_aid + self.curr_aid = min_aid + + # 已有curr_aid情况下,去自增这个值,目的是防止每次都要跑一次init_curr_aid + async def is_latest_aid(self): + old_curr_aid = self.curr_aid + while True: + aid = self.curr_aid + code0 = await notifier.exec_func(-1, SubstanceRaffleHandlerTask.check_code, aid+1) + if code0: + code1 = await notifier.exec_func(-1, SubstanceRaffleHandlerTask.check_code, aid+2) + code2 = await notifier.exec_func(-1, SubstanceRaffleHandlerTask.check_code, aid+3) + # 最上面没更新,说明目前值最新了 + if code1 and code2: + break + else: + if not code2: + self.curr_aid += 3 + elif not code1: + self.curr_aid += 2 + else: + self.curr_aid += 1 + return old_curr_aid == self.curr_aid, old_curr_aid + + async def run(self): + if self.curr_aid is None: + await self.init_curr_aid() + aid = self.curr_aid + for id in range(aid - 15, aid + 1): + notifier.exec_task(-1, SubstanceRaffleHandlerTask, 0, id, delay_range=(0, 35)) + while True: + is_latest, old_curr_aid = await self.is_latest_aid() + if not is_latest: + for id in range(old_curr_aid+1, self.curr_aid+1): + notifier.exec_task(-1, SubstanceRaffleHandlerTask, 0, id, delay_range=(0, 10)) + await asyncio.sleep(60) + + + diff --git a/notifier.py b/notifier.py new file mode 100644 index 0000000..24808b5 --- /dev/null +++ b/notifier.py @@ -0,0 +1,95 @@ +# 总控制中心,外界调用task的入口 +import asyncio +from random import uniform + + +class Notifier: + def set_values(self, loop): + self.loop = loop + + def set_users(self, list_users): + # -2表示广播, -1表示super_user, >0表示普通 + self.users = list_users + self.super_userid = 0 + + # id >=0, -1 + async def notify(self, id, func, *args): + if id == -1: + id = self.super_userid + if 0 <= id < len(self.users): + result = await self.users[id].accept(func, *args) + return result + return None + + async def notify_all(self, func, *args): + for user in self.users: + result = await user.accept(func, *args) + # print('notify_all 结果', result) + return result + + # delay_range 是一个tuple,里面是左右区间 + # 接受id -2/-1/>=0, 输出id >=0 + def __set_delay(self, delay_range, id): + if delay_range is None: + delay_range = 0, 0 + if id == -2: + return tuple((i, uniform(*delay_range)) for i in range(len(self.users))) + if id == -1: + id = self.super_userid + return (id, uniform(*delay_range)), + + # 接受id >=0 + async def __exec_one_step(self, id, task, step, *args): + # print('当前请求', task, id, step, args) + func = task.target(step) + assert func is not None + results = await self.notify(id, func, *args) + # results为()或None,就terminate,不管是否到头,这里的设计是user的拒绝执行的功能 + # 返回必须是tuple/list! + # print('结果返回', results) + if results is None: + return + for new_step, *result in results: + # user的延迟执行功能实现 + if new_step == -1: + new_step = step + # print(f'本step结果:{result} 下一步:{new_step}') + delay, new_uid, *args = result + self.call_after(delay, new_uid, task, new_step, *args) + + def __exec_bg(self, *args): + asyncio.ensure_future(self.__exec_one_step(*args)) + + # 接受uid -2/-1/>=0 + def call_after(self, delay_range, id, *args): + for new_id, delay in self.__set_delay(delay_range, id): + # print(f'休息{delay}s {new_id}执行:{args}') + # 这里用callafter api把notify送到queue里面立刻退出,所以不会爆 + self.loop.call_later(delay, self.__exec_bg, new_id, *args) + +var = Notifier() + + +def set_values(loop): + var.set_values(loop) + + +def set_users(users): + var.set_users(users) + +# 一种真task,不需要返回值的(task里面多个函数) +# 一种伪task,需要立刻返回(task可以认为里面就一个函数) + + +# 不会返回值, task +def exec_task(id, task, step, *args, delay_range=None): + # print('测试task', id, task, step, *args, delay_range) + var.call_after(delay_range, id, task, step, *args) + +# 伪task +async def exec_func(id, func, *args): + if id == -2: + result = await var.notify_all(func, *args) + else: + result = await var.notify(id, func, *args) + return result diff --git a/raffle_handler.py b/raffle_handler.py new file mode 100644 index 0000000..66bee7b --- /dev/null +++ b/raffle_handler.py @@ -0,0 +1,41 @@ +import asyncio +import notifier + + +class RaffleHandler: + def __init__(self): + self.queue = asyncio.Queue() + + async def run(self): + while True: + raffle0 = await self.queue.get() + await asyncio.sleep(2) + list_raffle = [self.queue.get_nowait() for i in range(self.queue.qsize())] + list_raffle.append(raffle0) + # 后期考虑如何更好的压缩 + list_raffle = list(set(list_raffle)) + # print('raffle_handler', list_raffle) + for task, *args in list_raffle: + notifier.exec_task(-1, task, 0, *args, delay_range=(0, 2)) + + def push2queue(self, *args): + self.queue.put_nowait(args) + + def exec_at_once(self, task, *args): + notifier.exec_task(-1, task, 0, *args, delay_range=(0, 0)) + + +var = RaffleHandler() + +async def run(): + await var.run() + + +def push2queue(*args): + var.push2queue(*args) + + +def exec_at_once(task, *args): + var.exec_at_once(task, *args) + + diff --git a/reqs/custom.py b/reqs/custom.py new file mode 100644 index 0000000..b8ab5de --- /dev/null +++ b/reqs/custom.py @@ -0,0 +1,10 @@ +import utils +from bili_global import API_LIVE + +class BuyLatiaoReq: + # 其实与utils部分差不多,怀疑可能是新旧api + @staticmethod + async def fetch_livebili_userinfo_pc(user): + url = f'{API_LIVE}/xlive/web-ucenter/user/get_user_info' + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp diff --git a/reqs/guard_raffle_handler.py b/reqs/guard_raffle_handler.py new file mode 100644 index 0000000..9674aaf --- /dev/null +++ b/reqs/guard_raffle_handler.py @@ -0,0 +1,21 @@ +from bili_global import API_LIVE + + +class GuardRaffleHandlerReq: + @staticmethod + async def check(user, real_roomid): + url = f'{API_LIVE}/lottery/v1/Lottery/check_guard?roomid={real_roomid}' + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def join(user, real_roomid, raffle_id): + url = f"{API_LIVE}/lottery/v2/Lottery/join" + data = { + 'roomid': real_roomid, + 'id': raffle_id, + 'type': 'guard', + 'csrf_token': user.dict_bili['csrf'] + } + json_rsp = await user.bililive_session.request_json('POST', url, data=data, headers=user.dict_bili['pcheaders']) + return json_rsp diff --git a/reqs/live_daily_job.py b/reqs/live_daily_job.py new file mode 100644 index 0000000..9b2d2f4 --- /dev/null +++ b/reqs/live_daily_job.py @@ -0,0 +1,118 @@ +from bili_global import API_LIVE +from .utils import UtilsReq + + +class HeartBeatReq: + @staticmethod + async def pc_heartbeat(user): + url = f'{API_LIVE}/User/userOnlineHeart' + json_rsp = await user.bililive_session.request_json('POST', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def app_heartbeat(user): + temp_params = f'access_key={user.dict_bili["access_key"]}&{user.app_params}&ts={UtilsReq.curr_time()}' + sign = user.calc_sign(temp_params) + url = f'{API_LIVE}/mobile/userOnlineHeart?{temp_params}&sign={sign}' + payload = {'roomid': 23058, 'scale': 'xhdpi'} + json_rsp = await user.bililive_session.request_json('POST', url, data=payload, headers=user.dict_bili['appheaders']) + return json_rsp + + +class RecvHeartGiftReq: + @staticmethod + async def recv_heartgift(user): + url = f"{API_LIVE}/gift/v2/live/heart_gift_receive?roomid=3&area_v2_id=34" + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + +class OpenSilverBoxReq: + @staticmethod + async def check_time(user): + temp_params = f'access_key={user.dict_bili["access_key"]}&{user.app_params}&ts={UtilsReq.curr_time()}' + sign = user.calc_sign(temp_params) + GetTask_url = f'{API_LIVE}/mobile/freeSilverCurrentTask?{temp_params}&sign={sign}' + json_rsp = await user.bililive_session.request_json('GET', GetTask_url, headers=user.dict_bili['appheaders']) + return json_rsp + + @staticmethod + async def open_silver_box(user, timestart, timeend): + temp_params = f'access_key={user.dict_bili["access_key"]}&{user.app_params}&time_end={timeend}&time_start={timestart}&ts={UtilsReq.curr_time()}' + sign = user.calc_sign(temp_params) + url = f'{API_LIVE}/mobile/freeSilverAward?{temp_params}&sign={sign}' + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['appheaders']) + return json_rsp + + +class RecvDailyBagReq: + @staticmethod + async def recv_dailybag(user): + url = f'{API_LIVE}/gift/v2/live/receive_daily_bag' + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + +class SignReq: + @staticmethod + async def sign(user): + url = f'{API_LIVE}/sign/doSign' + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + +class WatchTvReq: + @staticmethod + async def watch_tv(user): + url = f'{API_LIVE}/activity/v1/task/receive_award' + data = {'task_id': 'double_watch_task'} + json_rsp = await user.bililive_session.request_json('POST', url, data=data, headers=user.dict_bili['appheaders']) + return json_rsp + + +class SignFansGroupsReq: + @staticmethod + async def fetch_groups(user): + url = "https://api.vc.bilibili.com/link_group/v1/member/my_groups" + json_rsp = await user.other_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def sign_group(user, group_id, owner_uid): + temp_params = f'access_key={user.dict_bili["access_key"]}&actionKey={user.dict_bili["actionKey"]}&appkey={user.dict_bili["appkey"]}&build={user.dict_bili["build"]}&device={user.dict_bili["device"]}&group_id={group_id}&mobi_app={user.dict_bili["mobi_app"]}&owner_id={owner_uid}&platform={user.dict_bili["platform"]}&ts={UtilsReq.curr_time()}' + sign = user.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 user.other_session.request_json('GET', url, headers=user.dict_bili['appheaders']) + return json_rsp + + +class SendGiftReq: + @staticmethod + async def fetch_gift_config(user): + url = f'{API_LIVE}/gift/v3/live/gift_config' + json_rsp = await user.bililive_session.request_json('GET', url) + return json_rsp + + @staticmethod + async def fetch_wearing_medal(user): + url = f'{API_LIVE}/live_user/v1/UserInfo/get_weared_medal' + data = { + 'uid': user.dict_bili['uid'], + 'csrf_token': '' + } + json_rsp = await user.bililive_session.request_json('POST', url, data=data, headers=user.dict_bili['pcheaders']) + return json_rsp + + +class ExchangeSilverCoinReq: + @staticmethod + async def silver2coin_web(user): + url = f'{API_LIVE}/pay/v1/Exchange/silver2coin' + data = { + "platform": 'pc', + "csrf_token": user.dict_bili['csrf'] + } + json_rsp = await user.bililive_session.request_json('POST', url, headers=user.dict_bili['pcheaders'], data=data) + return json_rsp + + diff --git a/reqs/login.py b/reqs/login.py new file mode 100644 index 0000000..8685b51 --- /dev/null +++ b/reqs/login.py @@ -0,0 +1,84 @@ +import base64 +from PIL import Image +from io import BytesIO +import requests +from .utils import UtilsReq + + +class LoginReq: + @staticmethod + async def logout(user): + url = 'https://passport.bilibili.com/login?act=exit' + json_rsp = await user.login_session.request_json('GET', url, headers=user.dict_bili['pcheaders'], is_login=True) + return json_rsp + + @staticmethod + async def fetch_key(user): + url = 'https://passport.bilibili.com/api/oauth2/getKey' + temp_params = f'appkey={user.dict_bili["appkey"]}' + sign = user.calc_sign(temp_params) + params = {'appkey': user.dict_bili['appkey'], 'sign': sign} + json_rsp = await user.login_session.request_json('POST', url, data=params, is_login=True) + return json_rsp + + @staticmethod + async def normal_login(user, url_name, url_password): + url = "https://passport.bilibili.com/api/v2/oauth2/login" + temp_params = f'appkey={user.dict_bili["appkey"]}&password={url_password}&username={url_name}' + sign = user.calc_sign(temp_params) + payload = f'appkey={user.dict_bili["appkey"]}&password={url_password}&username={url_name}&sign={sign}' + json_rsp = await user.login_session.request_json('POST', url, params=payload, is_login=True) + return json_rsp + + @staticmethod + async def captcha_login(user, url_name, url_password): + url = "https://passport.bilibili.com/captcha" + binary_rsp = await user.login_session.request_binary('GET', url) + + captcha = LoginReq.cnn_captcha(binary_rsp) + temp_params = f'actionKey={user.dict_bili["actionKey"]}&appkey={user.dict_bili["appkey"]}&build={user.dict_bili["build"]}&captcha={captcha}&device={user.dict_bili["device"]}&mobi_app={user.dict_bili["mobi_app"]}&password={url_password}&platform={user.dict_bili["platform"]}&username={url_name}' + sign = user.calc_sign(temp_params) + payload = f'{temp_params}&sign={sign}' + url = "https://passport.bilibili.com/api/v2/oauth2/login" + json_rsp = await user.login_session.request_json('POST', url, params=payload, is_login=True) + return json_rsp + + @staticmethod + async def is_token_usable(user): + list_url = f'access_key={user.dict_bili["access_key"]}&{user.app_params}&ts={UtilsReq.curr_time()}' + list_cookie = user.dict_bili['cookie'].split(';') + params = ('&'.join(sorted(list_url.split('&') + list_cookie))) + sign = user.calc_sign(params) + true_url = f'https://passport.bilibili.com/api/v2/oauth2/info?{params}&sign={sign}' + json_rsp = await user.login_session.request_json('GET', true_url, headers=user.dict_bili['appheaders'], is_login=True) + return json_rsp + + @staticmethod + async def refresh_token(user): + list_url = f'access_key={user.dict_bili["access_key"]}&access_token={user.dict_bili["access_key"]}&{user.app_params}&refresh_token={user.dict_bili["refresh_token"]}&ts={UtilsReq.curr_time()}' + list_cookie = user.dict_bili['cookie'].split(';') + params = ('&'.join(sorted(list_url.split('&') + list_cookie))) + sign = user.calc_sign(params) + payload = f'{params}&sign={sign}' + # print(payload) + url = f'https://passport.bilibili.com/api/v2/oauth2/refresh_token' + json_rsp = await user.login_session.request_json('POST', url, headers=user.dict_bili['appheaders'], params=payload, is_login=True) + return json_rsp + + @staticmethod + 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 + + @staticmethod + def input_captcha(content): + img = Image.open(BytesIO(content)) + # img.thumbnail(size) + img.show() + captcha = input('手动输入验证码') + return captcha diff --git a/reqs/main_daily_job.py b/reqs/main_daily_job.py new file mode 100644 index 0000000..e861a24 --- /dev/null +++ b/reqs/main_daily_job.py @@ -0,0 +1,108 @@ +from .utils import UtilsReq + + +class JudgeCaseReq: + @staticmethod + async def judge_case(user, case_id, decision): + url = 'http://api.bilibili.com/x/credit/jury/vote' + payload = { + "jsonp": "jsonp", + "cid": case_id, + "vote": decision, + "content": "", + "likes": "", + "hates": "", + "attr": "1", + "csrf": user.dict_bili['csrf'] + } + json_rsp = await user.other_session.request_json('POST', url, headers=user.dict_bili['pcheaders'], data=payload) + return json_rsp + + @staticmethod + async def fetch_case(user): + url = 'http://api.bilibili.com/x/credit/jury/caseObtain' + data = { + "jsonp": "jsonp", + "csrf": user.dict_bili['csrf'] + } + json_rsp = await user.other_session.request_json('POST', url, headers=user.dict_bili['pcheaders'], data=data) + return json_rsp + + @staticmethod + async def check_case_status(user, case_id): + headers = { + **(user.dict_bili['pcheaders']), + 'Referer': f'https://www.bilibili.com/judgement/vote/{case_id}', + } + url = f'https://api.bilibili.com/x/credit/jury/juryCase?jsonp=jsonp&callback=jQuery1720{UtilsReq.randomint()}_{UtilsReq.curr_time()}&cid={case_id}&_={UtilsReq.curr_time()}' + text_rsp = await user.other_session.request_text('GET', url, headers=headers) + # print(text_rsp) + return text_rsp + + @staticmethod + async def fetch_judged_cases(user): + headers = { + **(user.dict_bili['pcheaders']), + 'Referer': 'https://www.bilibili.com/judgement/index', + } + url = f'https://api.bilibili.com/x/credit/jury/caseList?callback=jQuery1720{UtilsReq.randomint()}_{UtilsReq.curr_time()}&pn=1&ps=25&_={UtilsReq.curr_time()}' + json_rsp = await user.other_session.request_json('GET', url, headers=headers) + return json_rsp + + +class BiliMainReq: + @staticmethod + async def send_coin2video(user, aid, num_sent): + url = 'https://api.bilibili.com/x/web-interface/coin/add' + pcheaders = { + **(user.dict_bili['pcheaders']), + 'referer': f'https://www.bilibili.com/video/av{aid}' + } + data = { + 'aid': aid, + 'multiply': num_sent, + 'cross_domain': 'true', + 'csrf': user.dict_bili['csrf'] + } + json_rsp = await user.other_session.request_json('POST', url, headers=pcheaders, data=data) + return json_rsp + + @staticmethod + async def heartbeat(user, aid, cid): + url = 'https://api.bilibili.com/x/report/web/heartbeat' + data = { + 'aid': aid, + 'cid': cid, + 'mid': user.dict_bili['uid'], + 'csrf': user.dict_bili['csrf'], + 'played_time': 0, + 'realtime': 0, + 'start_ts': UtilsReq.curr_time(), + 'type': 3, + 'dt': 2, + 'play_type': 1 + } + json_rsp = await user.other_session.request_json('POST', url, data=data, headers=user.dict_bili['pcheaders']) + return json_rsp + + async def share_video(user, aid): + url = 'https://api.bilibili.com/x/web-interface/share/add' + data = {'aid': aid, 'jsonp': 'jsonp', 'csrf': user.dict_bili['csrf']} + json_rsp = await user.other_session.request_json('POST', url, data=data, headers=user.dict_bili['pcheaders']) + return json_rsp + + async def aid2cid(user, aid): + url = f'https://www.bilibili.com/widget/getPageList?aid={aid}' + json_rsp = await user.other_session.request_json('GET', url) + return json_rsp + + async def fetch_uper_videos(user, mid, page): + url = f'https://space.bilibili.com/ajax/member/getSubmitVideos?mid={mid}&pagesize=100&page={page}' + json_rsp = await user.other_session.request_json('GET', url) + return json_rsp + + async def fetch_top_videos(user): + url = 'https://www.bilibili.com/ranking/all/0/0/1/' + text_tsp = await user.other_session.request_text('GET', url) + return text_tsp + diff --git a/reqs/storm_raffle_handler.py b/reqs/storm_raffle_handler.py new file mode 100644 index 0000000..3af6415 --- /dev/null +++ b/reqs/storm_raffle_handler.py @@ -0,0 +1,23 @@ +from bili_global import API_LIVE + + +class StormRaffleHandlerReq: + @staticmethod + async def check(user, room_id): + url = f"{API_LIVE}/lottery/v1/Storm/check?roomid={room_id}" + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def join(user, raffle_id): + url = f'{API_LIVE}/lottery/v1/Storm/join' + data = { + "id": raffle_id, + "color": "16777215", + "captcha_token": "", + "captcha_phrase": "", + "token": "", + "csrf_token": user.dict_bili['csrf'] + } + json_rsp = await user.bililive_session.request_json('POST', url, data=data, headers=user.dict_bili['pcheaders']) + return json_rsp diff --git a/reqs/substance_raffle_handler.py b/reqs/substance_raffle_handler.py new file mode 100644 index 0000000..dc611a8 --- /dev/null +++ b/reqs/substance_raffle_handler.py @@ -0,0 +1,15 @@ +from bili_global import API_LIVE + + +class SubstanceRaffleHandlerReq: + @staticmethod + async def check(user, aid): + url = f"{API_LIVE}/lottery/v1/box/getStatus?aid={aid}" + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def get_gift_of_lottery(user, aid, num): + url = f'{API_LIVE}/lottery/v1/box/draw?aid={aid}&number={num + 1}' + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp diff --git a/reqs/tv_raffle_handler.py b/reqs/tv_raffle_handler.py new file mode 100644 index 0000000..48664ec --- /dev/null +++ b/reqs/tv_raffle_handler.py @@ -0,0 +1,29 @@ +from bili_global import API_LIVE + +class TvRaffleHandlerReq: + @staticmethod + async def check(user, real_roomid): + url = f"{API_LIVE}/gift/v3/smalltv/check?roomid={real_roomid}" + response = await user.bililive_session.request_json('GET', url) + return response + + @staticmethod + async def join(user, real_roomid, TV_raffleid): + url = f"{API_LIVE}/gift/v3/smalltv/join" + payload = { + "roomid": real_roomid, + "raffleId": TV_raffleid, + "type": "Gift", + "csrf_token": '' + } + + response = await user.bililive_session.request_json('POST', url, data=payload, headers=user.dict_bili['pcheaders']) + return response + + @staticmethod + async def notice(user, TV_roomid, TV_raffleid): + url = f"{API_LIVE}/gift/v3/smalltv/notice?type=small_tv&raffleId={TV_raffleid}" + response = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return response + + diff --git a/reqs/utils.py b/reqs/utils.py new file mode 100644 index 0000000..fe69588 --- /dev/null +++ b/reqs/utils.py @@ -0,0 +1,163 @@ +# 不具有任何意义,仅仅是常见func + +import time +from random import randint +from bili_global import API_LIVE + + +class UtilsReq: + @staticmethod + def randomint(): + return ''.join(str(randint(0, 9)) for _ in range(17)) + + @staticmethod + def curr_time(): + return int(time.time()) + + @staticmethod + async def post_watching_history(user, room_id): + data = { + "room_id": room_id, + "csrf_token": user.dict_bili['csrf'] + } + url = f"{API_LIVE}/room/v1/Room/room_entry_action" + response = await user.bililive_session.request_json('POST', url, data=data, headers=user.dict_bili['pcheaders']) + return response + + @staticmethod + async def init_room(user, roomid): + url = f"{API_LIVE}/room/v1/Room/room_init?id={roomid}" + response = await user.bililive_session.request_json('GET', url) + return response + + @staticmethod + async def get_rooms_by_area(user, areaid): + url = f'{API_LIVE}/room/v1/area/getRoomList?platform=web&parent_area_id={areaid}&cate_id=0&area_id=0&sort_type=online&page=1&page_size=15' + json_rsp = await user.bililive_session.request_json('GET', url) + return json_rsp + + @staticmethod + async def get_room_info(user, roomid): + url = f"{API_LIVE}/room/v1/Room/get_info?room_id={roomid}" + json_rsp = await user.bililive_session.request_json('GET', url) + return json_rsp + + @staticmethod + async def fetch_giftbags(user): + url = f'{API_LIVE}/gift/v2/gift/bag_list' + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def send_gift(user, gift_id, num_sent, bag_id, ruid, biz_id): + url = f'{API_LIVE}/gift/v2/live/bag_send' + data = { + 'uid': user.dict_bili['uid'], + 'gift_id': gift_id, + 'ruid': ruid, + 'gift_num': num_sent, + 'bag_id': bag_id, + 'platform': 'pc', + 'biz_code': 'live', + 'biz_id': biz_id, + 'rnd': UtilsReq.curr_time(), + 'storm_beat_id': '0', + 'metadata': '', + 'price': '0', + 'csrf_token': user.dict_bili['csrf'] + } + json_rsp = await user.bililive_session.request_json('POST', url, headers=user.dict_bili['pcheaders'], data=data) + return json_rsp + + @staticmethod + async def buy_gift(user, gift_id, num_sent, ruid, biz_id, coin_type): + url = f'{API_LIVE}/gift/v2/gift/send' + data = { + 'uid': user.dict_bili['uid'], + 'gift_id': gift_id, + 'ruid': ruid, + 'gift_num': num_sent, + 'coin_type': coin_type, + 'bag_id': 0, + 'platform': 'pc', + 'biz_code': 'live', + 'biz_id': biz_id, + 'rnd': UtilsReq.curr_time(), + 'storm_beat_id': '0', + 'metadata': '', + 'price': '0', + 'csrf_token': user.dict_bili['csrf'] + } + json_rsp = await user.bililive_session.request_json('POST', url, headers=user.dict_bili['pcheaders'], data=data) + return json_rsp + + @staticmethod + async def fetch_medals(user): + url = f'{API_LIVE}/i/api/medal?page=1&pageSize=50' + json_rsp = await user.bililive_session.request_json('POST', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def fetch_bilimain_tasks(user): + url = 'https://account.bilibili.com/home/reward' + json_rsp = await user.other_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def fetch_livebili_tasks(user): + url = f'{API_LIVE}/i/api/taskInfo' + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + # 有个其他的api,主页那里,但是类似于judge查询那样,json隐藏在text里面,恶心 + @staticmethod + async def fetch_bilimain_userinfo(user): + url = 'https://account.bilibili.com/home/userInfo' + json_rsp = await user.other_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def fetch_livebili_userinfo_pc(user): + url = f"{API_LIVE}/i/api/liveinfo" + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def fetch_livebili_userinfo_ios(user): + url = f'{API_LIVE}/mobile/getUser?access_key={user.dict_bili["access_key"]}&platform=ios' + json_rsp = await user.bililive_session.request_json('GET', url) + return json_rsp + + @staticmethod + async def fetch_capsule_info(user): + url = f'{API_LIVE}/xlive/web-ucenter/v1/capsule/get_detail?from=web' + json_rsp = await user.bililive_session.request_json('GET', url, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def open_capsule(user, num_opened): + url = f'{API_LIVE}/xlive/web-ucenter/v1/capsule/open_capsule' + data = { + 'type': 'normal', + "count": num_opened, + 'csrf_token': user.dict_bili['csrf'], + 'csrf': user.dict_bili['csrf'] + } + json_rsp = await user.bililive_session.request_json('POST', url, data=data, headers=user.dict_bili['pcheaders']) + return json_rsp + + @staticmethod + async def send_danmu(user, msg, room_id): + url = f'{API_LIVE}/msg/send' + data = { + 'color': '16777215', + 'fontsize': '25', + 'mode': '1', + 'msg': msg, + 'rnd': '0', + 'roomid': int(room_id), + 'csrf_token': user.dict_bili['csrf'], + 'csrf': user.dict_bili['csrf'] + } + json_rsp = await user.bililive_session.request_json('POST', url, headers=user.dict_bili['pcheaders'], data=data) + return json_rsp diff --git a/run.py b/run.py new file mode 100644 index 0000000..9fd6926 --- /dev/null +++ b/run.py @@ -0,0 +1,95 @@ +import sys +import threading +import asyncio +from os import path +import connect +import conf_loader +import notifier +import raffle_handler +import bili_statistics +from bili_console import Biliconsole +import printer +from user import User +from tasks.login import LoginTask +from tasks.live_daily_job import ( + HeartBeatTask, + RecvHeartGiftTask, + OpenSilverBoxTask, + RecvDailyBagTask, + SignTask, + WatchTvTask, + SignFansGroupsTask, + SendGiftTask, + ExchangeSilverCoinTask, +) +from tasks.main_daily_job import ( + JudgeCaseTask, + BiliMainTask + +) +from monitor_substance_raffle import SubstanceRaffleMonitor + +root_path = path.dirname(path.realpath('__file__')) +conf_loader.set_path(root_path) + +if sys.platform == 'win32': + loop = asyncio.ProactorEventLoop() + asyncio.set_event_loop(loop) +else: + loop = asyncio.get_event_loop() + +dict_user = conf_loader.read_user() +dict_bili = conf_loader.read_bili() +dict_color = conf_loader.read_color() +printer.init_config(dict_color, dict_user['print_control']['danmu']) +area_ids = dict_user['other_control']['area_ids'] + +users = [] +task_control = dict_user['task_control'] +for i, user_info in enumerate(dict_user['users']): + users.append(User(i, user_info, task_control, dict_bili)) + + +notifier.set_values(loop) +notifier.set_users(users) +bili_statistics.init_area_num(len(area_ids)) + + + +loop.run_until_complete(asyncio.wait([notifier.exec_func(-2, LoginTask.handle_login_status)])) + +# users[1].fall_in_jail() + +console_thread = threading.Thread(target=Biliconsole(loop).cmdloop) +console_thread.start() + +danmu_tasks = [connect.RaffleConnect(i).run() for i in area_ids] + +yj_danmu_roomid = dict_user['other_control']['raffle_minitor_roomid'] +danmu_tasks.append(connect.YjConnection(yj_danmu_roomid).run()) + +default_monitor_roomid = dict_user['other_control']['default_monitor_roomid'] +connect.init_danmu_roomid(default_monitor_roomid) +danmu_tasks.append(connect.run_danmu()) + + +notifier.exec_task(-2, HeartBeatTask, 0, delay_range=(0, 5)) +notifier.exec_task(-2, RecvHeartGiftTask, 0, delay_range=(0, 5)) +notifier.exec_task(-2, OpenSilverBoxTask, 0, delay_range=(0, 5)) +notifier.exec_task(-2, RecvDailyBagTask, 0, delay_range=(0, 5)) +notifier.exec_task(-2, SignTask, 0, delay_range=(0, 5)) +notifier.exec_task(-2, WatchTvTask, 0, delay_range=(0, 5)) +notifier.exec_task(-2, SignFansGroupsTask, 0, delay_range=(0, 5)) +notifier.exec_task(-2, SendGiftTask, 0, delay_range=(0, 5)) +notifier.exec_task(-2, ExchangeSilverCoinTask, 0, delay_range=(0, 5)) +notifier.exec_task(-2, JudgeCaseTask, 0, delay_range=(0, 5)) +notifier.exec_task(-2, BiliMainTask, 0, delay_range=(0, 5)) + +other_tasks = [ + raffle_handler.run(), + # SubstanceRaffleMonitor().run() + ] + +loop.run_until_complete(asyncio.wait(other_tasks+danmu_tasks)) +console_thread.join() + diff --git a/states.py b/states.py deleted file mode 100644 index 2137a46..0000000 --- a/states.py +++ /dev/null @@ -1,161 +0,0 @@ -from datetime import datetime -import random -from task import Task -import printer -import asyncio - - -class BaseState(): - black_list = { - 'handle_1_activity_raffle': 2, - 'handle_1_TV_raffle': 2, - 'handle_1_substantial_raffle': 2, - 'handle_1_guard_raffle': 2, - 'open_silver_box': 1, - 'post_watching_history': 2, - 'fetch_heart_gift': 1 - } - - def check_status(self, func, value): - pass - - -# 工作状态类 -class DayState(BaseState): - def check_status(self, func, value): - # print("工作,精神百倍") - return 0, None - - -# 睡眠状态 -class NightState(BaseState): - def check_status(self, func, value): - # print("睡觉了") - now = datetime.now() - if func == 'daily_task': - seconds = (3 - now.hour - 1) * 3600 + (60 - now.minute - 1) * 60 + (60 - now.second) - sleeptime = seconds + random.uniform(0, 30) - return 1, sleeptime - else: - return self.black_list.get(func, 0), None - - -class JailState(BaseState): - def check_status(self, func, value): - # print('因为进入了监狱') - if func == 'daily_task': - return self.black_list.get(value[0], 0), 1800 - else: - return self.black_list.get(func, 0), 1800 - - -class FreeState(BaseState): - def check_status(self, func, value): - # print('因为是个自由人') - return 0, None - - -class LoginState(BaseState): - def check_status(self): - # print('因为已经正常登陆') - return True - - -class LogoutState(BaseState): - def check_status(self): - # print('因为未正常登陆') - return False - - -class UserStates(): - state_night = NightState() - state_day = DayState() - state_jail = JailState() - state_free = FreeState() - state_login = LoginState() - state_logout = LogoutState() - - def __init__(self, user_id, user_name): - self.time_state = self.state_day - self.work_state = self.state_free - self.log_state = self.state_login - self.user_id = user_id - self.user_name = user_name - self.delay_tasks = [] - self.delay_requests = [] - - def clean_delay_tasks(self): - for func, values in self.delay_tasks: - time_delay = random.uniform(0, 30) - Task().call_after(func, time_delay, values, self.user_id) - del self.delay_tasks[:] - - def clean_delay_requests(self): - for future in self.delay_requests: - future.set_result(True) - del self.delay_requests[:] - - def go_to_bed(self): - # print('{休眠}') - self.time_state = self.state_night - - def wake_up(self): - # print('{起床}') - self.time_state = self.state_day - self.clean_delay_tasks() - - def fall_in_jail(self): - # print('{入狱}') - self.work_state = self.state_jail - - def out_of_jail(self): - # print('{自由}') - self.work_state = self.state_free - self.clean_delay_tasks() - - def logout(self): - print('{未登陆}') - self.log_state = self.state_logout - - def login(self): - print('{已经登陆}') - self.log_state = self.state_login - self.clean_delay_requests() - - def printer_with_id(self, list_msg, tag_time=False): - list_msg[0] += f'(用户id:{self.user_id} 用户名:{self.user_name})' - printer.info(list_msg, tag_time) - - def print_state(self): - work_state = '恭喜中奖' if self.work_state == self.state_jail else '未进入小黑屋' - time_state = '白天工作' if self.time_state == self.state_day else '夜晚休眠' - self.printer_with_id([f'{self.delay_tasks}'], True) - return work_state, time_state - - def check_status(self, func, values): - code, sleeptime = self.time_state.check_status(func, values) - if code: - # print(code, sleeptime) - pass - else: - code, sleeptime = (self.work_state.check_status(func, values)) - # print(code, sleeptime) - - # print('+++++++++++++++++++++++') - if code == 1: - # self.printer_with_id([f'sleep模式, 推迟执行{func} {values}'], True) - self.delay_tasks.append((func, values)) - return 1 - elif code == 2: - # self.printer_with_id([f'drop模式, 不执行{func} {values}'], True) - return 2 - return 0 - - async def check_log_state(self, request): - # print('正在检查', request) - code = self.log_state.check_status() - if not code: - future = asyncio.Future() - self.delay_requests.append(future) - await future - return code diff --git a/task.py b/task.py deleted file mode 100644 index 7b0b1bb..0000000 --- a/task.py +++ /dev/null @@ -1,177 +0,0 @@ -import time -import asyncio -import random -from datetime import datetime - - -def CurrentTime(): - currenttime = int(time.time()) - return currenttime - - -class Singleton(type): - _instances = {} - - def __call__(cls, *args, **kwargs): - if cls not in cls._instances: - cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) - return cls._instances[cls] - - -class Messenger(metaclass=Singleton): - def __init__(self, users=None, var_super_user=None, loop=None, is_need_queue=False): - if is_need_queue: - self.queue = asyncio.Queue() - self.loop = loop - self._observers = users - self._var_super_user = var_super_user - - async def call(self, func, value, id=None): - # print('小黑屋状态:', self.dict_user_status) - if id is None: - list_tasks = [] - for i, user in enumerate(self._observers): - task = asyncio.ensure_future(user.update(func, value)) - list_tasks.append(task) - if list_tasks: - await asyncio.wait(list_tasks) - elif id >= 0: - if id >= len(self._observers): - return 0 - user = self._observers[id] - return await user.update(func, value) - else: - user = self._var_super_user - answer = await user.update(func, value) - return answer - - async def call_one_by_one(self, func, values, id=None): - if id is None: - for i, user in enumerate(self._observers): - await user.update(func, values) - elif id >= 0: - if id >= len(self._observers): - return 0 - user = self._observers[id] - return await user.update(func, values) - else: - user = self._var_super_user - answer = await user.update(func, values) - return answer - - def call_backgroud(self, i): - asyncio.ensure_future(self.call(*i)) - - def call_after(self, func, delay, tuple_values, id=None, time_range=None): - if time_range is None: - value = (func, tuple_values, id) - self.loop.call_later(delay, self.call_backgroud, value) - else: - for id, add_time in self.set_delay_times(time_range): - value = (func, tuple_values, id) - self.loop.call_later(delay + add_time, self.call_backgroud, value) - - def call_at(self, func, time_expected, tuple_values, id=None, time_range=None): - current_time = CurrentTime() - delay = time_expected - current_time - self.call_after(func, delay, tuple_values, id=id, time_range=time_range) - - def set_delay_times(self, time_range): - return ((i, random.uniform(0, time_range)) for i in range(len(self._observers))) - - -# 被观测的 -class RaffleHandler(Messenger): - - async def join_raffle(self): - while True: - raffle = await self.queue.get() - await asyncio.sleep(3) - list_raffle0 = [self.queue.get_nowait() for i in range(self.queue.qsize())] - list_raffle0.append(raffle) - list_raffle = list(set(list_raffle0)) - - tasklist = [] - for i in list_raffle: - task = asyncio.ensure_future(self.handle_1_roomid_raffle(i)) - tasklist.append(task) - await asyncio.wait(tasklist) - - def push2queue(self, value, func, id=None): - self.queue.put_nowait((value, func, id)) - - async def handle_TV_raffle(self, room_id): - if (await self.call('check_if_normal_room', (room_id,), -1)): - self.call_after('post_watching_history', 0, (room_id,), time_range=60) - await self.call('handle_1_room_TV', (room_id,), -1) - - async def handle_guard_raffle(self, room_id, raffle_id=None): - if raffle_id is not None: - self.call_after('post_watching_history', 0, (room_id,), time_range=60) - await self.call('handle_1_room_guard', (room_id, raffle_id), -1) - return - if (await self.call('check_if_normal_room', (room_id,), -1)): - self.call_after('post_watching_history', 0, (room_id,), time_range=60) - await self.call('handle_1_room_guard', (room_id,), -1) - - async def handle_1_roomid_raffle(self, i): - if i[1] in ['handle_TV_raffle', 'handle_guard_raffle']: - await getattr(self, i[1])(*i[0]) - else: - print('hhjjkskddrsfvsfdfvdfvvfdvdvdfdfffdfsvh', i) - - -class Task(Messenger): - - def init(self): - self.call_after('daily_task', 0, ('sliver2coin',), time_range=25) - self.call_after('daily_task', 0, ('doublegain_coin2silver',), time_range=25) - self.call_after('daily_task', 0, ('DoSign',), time_range=25) - self.call_after('daily_task', 0, ('Daily_bag',), time_range=25) - self.call_after('daily_task', 0, ('Daily_Task',), time_range=25) - self.call_after('daily_task', 0, ('link_sign',), time_range=25) - # self.call_after('daily_task', 0, ('auto_send_gift',), time_range=25) - self.call_after('daily_task', 0, ('BiliMainTask',), time_range=25) - self.call_after('daily_task', 0, ('judge',), time_range=25) - self.call_after('daily_task', 0, ('open_silver_box',), time_range=25) - self.call_after('daily_task', 0, ('heartbeat',), time_range=25) - self.call_after('daily_task', 0, ('fetch_heart_gift',), time_range=25) - - -class StateTask(Messenger): - def wake_up_all(self): - for user in (self._observers): - user.wake_up() - - def release_all(self): - for user in (self._observers): - user.out_of_jail() - - def sleep_all(self): - for user in (self._observers): - user.go_to_bed() - - async def run_workstate(self): - while True: - await asyncio.sleep(4 * 3600) - # await asyncio.sleep(120) - self.release_all() - - async def run_timestate(self): - while True: - sleeptime = 0 - now = datetime.now() - if now.hour * 60 + now.minute < 180: - self.sleep_all() - seconds = (3 - now.hour - 1) * 3600 + (60 - now.minute - 1) * 60 + (60 - now.second) - # 防止时间卡得过死 - sleeptime = seconds + random.uniform(60, 90) - sleeptime = max(0, seconds) - else: - self.wake_up_all() - seconds = (24 - now.hour - 1) * 3600 + (60 - now.minute - 1) * 60 + (60 - now.second) - sleeptime = seconds + random.uniform(60, 90) - await asyncio.sleep(sleeptime) - - - diff --git a/tasks/custom.py b/tasks/custom.py new file mode 100644 index 0000000..2f58f07 --- /dev/null +++ b/tasks/custom.py @@ -0,0 +1,58 @@ +# 理论上项目已有的task不要相互引用,只能引用utils的东西,防止交叉,但是自定义的无所谓,因为绝对不可能交叉 +from tasks.live_daily_job import SendGiftTask +from tasks.utils import UtilsTask +from reqs.custom import BuyLatiaoReq + + +class SendLatiaoTask: + @staticmethod + def target(step): + if step == 0: + return SendLatiaoTask.send_latiao + return None + + # 到达users的顶之后,notify函数返回None,自然会停止 + @staticmethod + async def send_latiao(user, room_id, num_max): + gift_bags = await SendGiftTask.fetch_giftbags(user) + num_finished = 0 + send_giftbags = [] + for gift in gift_bags: + gift_id = int(gift[0]) + left_time = gift[3] + if gift_id == 1 and left_time is not None: + send_giftbags.append(gift[:3]) + print(user.id, send_giftbags) + + for gift_id, gift_num, bag_id in send_giftbags: + if num_max - num_finished >= gift_num: + num_sent = gift_num + elif num_max > num_finished: + num_sent = num_max - num_finished + else: + continue + num_finished += num_sent + await UtilsTask.send_gift(user, room_id, num_sent, bag_id, gift_id) + user.info([f'一共送出{num_finished}个辣条给{room_id}'], True) + if num_max - num_finished == 0: + return None + return (0, (0, 1.5), user.id + 1, room_id, num_max - num_finished), + + +class BuyLatiaoTask: + @staticmethod + async def fetch_silver(user): + json_rsp = await user.req_s(BuyLatiaoReq.fetch_livebili_userinfo_pc, user) + if not json_rsp['code']: + silver = json_rsp['data']['silver'] + return silver + + + @staticmethod + async def clean_latiao(user, room_id): + gift_id = 1 + num_sent = 1 + coin_type = 'silver' + num_sent = int((await BuyLatiaoTask.fetch_silver(user)) / 100) + await UtilsTask.buy_gift(user, room_id, num_sent, coin_type, gift_id) + diff --git a/tasks/guard_raffle_handler.py b/tasks/guard_raffle_handler.py new file mode 100644 index 0000000..d48ba78 --- /dev/null +++ b/tasks/guard_raffle_handler.py @@ -0,0 +1,54 @@ +import asyncio +import bili_statistics +from reqs.guard_raffle_handler import GuardRaffleHandlerReq +from tasks.utils import UtilsTask + + +class GuardRaffleHandlerTask: + @staticmethod + def target(step): + if step == 0: + return GuardRaffleHandlerTask.check + if step == 1: + return GuardRaffleHandlerTask.join + return None + + @staticmethod + async def check(user, real_roomid, raffle_id=None): + if not await UtilsTask.is_normal_room(user, real_roomid): + return + if raffle_id is not None: + json_rsp = {'data': [{'id': raffle_id, 'time': 65}]} + else: + for i in range(10): + json_rsp = await user.req_s(GuardRaffleHandlerReq.check, user, real_roomid) + # print(json_rsp) + if json_rsp['data']: + break + await asyncio.sleep(1) + else: + print(f'{real_roomid}没有guard或者guard已经领取') + return + next_step_settings = [] + for j in json_rsp['data']: + raffle_id = j['id'] + # 总督长达一天,额外处理 + max_wait = min(j['time'] - 15, 240) + if not bili_statistics.is_raffleid_duplicate(raffle_id): + print('本次获取到的抽奖id为', raffle_id) + next_step_setting = (1, (0, max_wait), -2, real_roomid, raffle_id) + next_step_settings.append(next_step_setting) + bili_statistics.add2raffle_ids(raffle_id) + return next_step_settings + + @staticmethod + async def join(user, real_roomid, raffle_id): + # print('参与', raffle_id) + await UtilsTask.enter_room(user, real_roomid) + json_rsp = await user.req_s(GuardRaffleHandlerReq.join, user, real_roomid, raffle_id) + user.info([f'参与了房间{real_roomid:^9}的大航海抽奖'], True) + if not json_rsp['code']: + user.info([f'# 房间{real_roomid:^9}大航海抽奖结果: {json_rsp["data"]["message"]}'], with_userid=False) + bili_statistics.add2joined_raffles('大航海(合计)', user.id) + else: + print(json_rsp) diff --git a/tasks/live_daily_job.py b/tasks/live_daily_job.py new file mode 100644 index 0000000..62e7bdd --- /dev/null +++ b/tasks/live_daily_job.py @@ -0,0 +1,306 @@ +import asyncio +import utils +from .utils import UtilsTask +from reqs.live_daily_job import ( + HeartBeatReq, + RecvHeartGiftReq, + OpenSilverBoxReq, + RecvDailyBagReq, + SignReq, + WatchTvReq, + SignFansGroupsReq, + SendGiftReq, + ExchangeSilverCoinReq, +) + + +class HeartBeatTask: + @staticmethod + def target(step): + if step == 0: + return HeartBeatTask.heart_beat + return None + + @staticmethod + async def heart_beat(user): + json_rsp = await user.req_s(HeartBeatReq.pc_heartbeat, user) + # print(json_rsp) + user.info(['心跳包(5分钟左右间隔)'], True) + json_rsp = await user.req_s(HeartBeatReq.app_heartbeat, user) + print(json_rsp) + return (0, (280, 300), user.id), + + +class RecvHeartGiftTask: + @staticmethod + def target(step): + if step == 0: + return RecvHeartGiftTask.recv_heartgift + return None + + @staticmethod + async def recv_heartgift(user): + json_rsp = await user.req_s(RecvHeartGiftReq.recv_heartgift, user) + if json_rsp['code'] == 400: + user.fall_in_jail() + return (0, (0, 0), user.id), + return (0, (280, 300), user.id), + + +class OpenSilverBoxTask: + @staticmethod + def target(step): + if step == 0: + return OpenSilverBoxTask.open_silver_box + return None + + @staticmethod + async def open_silver_box(user): + while True: + user.info(["检查宝箱状态"], True) + temp = await user.req_s(OpenSilverBoxReq.check_time, user) + # print (temp['code']) #宝箱领完返回的code为-10017 + if temp['code'] == -10017: + user.info(["# 今日宝箱领取完毕"]) + json_rsp = None + else: + time_start = temp['data']['time_start'] + time_end = temp['data']['time_end'] + json_rsp = await user.req_s(OpenSilverBoxReq.open_silver_box, user, time_start, time_end) + if json_rsp is None or json_rsp['code'] == -10017 or json_rsp['code'] == -800: + sleeptime = utils.seconds_until_tomorrow() + 300 + return (0, (sleeptime, sleeptime+30), user.id), + elif not json_rsp['code']: + user.info(["# 打开了宝箱"]) + elif json_rsp['code'] == 400: + user.info(["# 宝箱开启中返回了小黑屋提示"]) + user.fall_in_jail() + # 马上继续调用,由下一次的user去supend这个task + return (0, (0, 0), user.id), + else: + user.info(["# 继续等待宝箱冷却..."]) + sleeptime = (json_rsp['data'].get('surplus', 3)) * 60 + 5 + return (0, (sleeptime, sleeptime+30), user.id), + + +class RecvDailyBagTask: + @staticmethod + def target(step): + if step == 0: + return RecvDailyBagTask.recv_dailybag + return None + + @staticmethod + async def recv_dailybag(user): + json_rsp = await user.req_s(RecvDailyBagReq.recv_dailybag, user) + for i in json_rsp['data']['bag_list']: + user.info([f'# 获得-{i["bag_name"]}-成功']) + sleeptime = 21600 + return (0, (sleeptime, sleeptime+30), user.id), + + +class SignTask: + @staticmethod + def target(step): + if step == 0: + return SignTask.sign + return None + + @staticmethod + async def sign(user): + json_rsp = await user.req_s(SignReq.sign, user) + user.info([f'签到状态: {json_rsp["msg"]}'], True) + if json_rsp['code'] == -500 and '已' in json_rsp['msg']: + sleeptime = utils.seconds_until_tomorrow() + 300 + else: + sleeptime = 350 + return (0, (sleeptime, sleeptime+30), user.id), + + +class WatchTvTask: + @staticmethod + def target(step): + if step == 0: + return WatchTvTask.watch_tv + return None + + @staticmethod + async def watch_tv(user): + # -400 done/not yet + json_rsp = await user.req_s(WatchTvReq.watch_tv, user) + user.info([f'双端观看直播: {json_rsp["msg"]}'], True) + if json_rsp['code'] == -400 and '已' in json_rsp['msg']: + sleeptime = utils.seconds_until_tomorrow() + 300 + else: + sleeptime = 350 + return (0, (sleeptime, sleeptime+30), user.id), + + +class SignFansGroupsTask: + @staticmethod + def target(step): + if step == 0: + return SignFansGroupsTask.sign_groups + return None + + @staticmethod + async def sign_groups(user): + json_rsp = await user.req_s(SignFansGroupsReq.fetch_groups, user) + groups = [(i['group_id'], i['owner_uid']) for i in json_rsp['data']['list']] + if groups: + tasks = [] + for group_id, owner_uid in groups: + task = asyncio.ensure_future(SignFansGroupsTask.sign_group(user, group_id, owner_uid)) + tasks.append(task) + await asyncio.wait(tasks, return_when=asyncio.ALL_COMPLETED) + sleeptime = 21600 + return (0, (sleeptime, sleeptime+30), user.id), + + @staticmethod + async def sign_group(user, group_id, owner_uid): + json_rsp = await user.req_s(SignFansGroupsReq.sign_group, user, group_id, owner_uid) + if not json_rsp['code']: + data = json_rsp['data'] + if data['status']: + user.info([f'# 应援团 {group_id} 已应援过']) + else: + user.info([f'# 应援团 {group_id} 应援成功,获得 {data["add_num"]} 点亲密度']) + else: + user.info([f'# 应援团 {group_id} 应援失败']) + + +class SendGiftTask: + @staticmethod + def target(step): + if step == 0: + return SendGiftTask.send_gift + return None + + @staticmethod + async def fetch_giftbags(user): + gift_bags = await UtilsTask.fetch_giftbags(user) + results = [] + for bag_id, gift_id, gift_num, _, _, left_time in gift_bags: + results.append([gift_id, gift_num, bag_id, left_time]) + return results + + @staticmethod + async def fetch_wearing_medal(user): + json_rsp = await user.req_s(SendGiftReq.fetch_wearing_medal, user) + if not json_rsp['code']: + data = json_rsp['data'] + if data: + room_id = data['roominfo']['room_id'] + remain_intimacy = int(data['day_limit']) - int(data['today_feed']) + medal_name = data['medal_name'] + return [(room_id, remain_intimacy, medal_name), ] + else: + # print('暂无佩戴任何勋章') + return [] + + @staticmethod + async def send_expiring_gift(user): + if not user.task_ctrl['clean-expiring-gift']: + return + gift_bags = await SendGiftTask.fetch_giftbags(user) + room_id = user.task_ctrl['clean-expiring-gift2room'] + time_set = user.task_ctrl['set-expiring-time'] + # filter 用过期来过滤 + expiring_giftbags = [] + for gift in gift_bags: + left_time = gift[3] + if left_time is not None and 0 < int(left_time) < time_set: + expiring_giftbags.append(gift[:3]) + if expiring_giftbags: + print('发现即将过期的礼物') + if user.task_ctrl['clean_expiring_gift2all_medal']: + print('正在清理过期礼物到用户勋章') + medals = await UtilsTask.fetch_medals(user) + expiring_giftbags = await SendGiftTask.fill_intimacy(user, expiring_giftbags, medals) + + print('正在清理过期礼物到指定房间') + for gift_id, gift_num, bag_id in expiring_giftbags: + await UtilsTask.send_gift(user, room_id, gift_num, bag_id, gift_id) + else: + print('未发现即将过期的礼物') + + @staticmethod + async def send_medal_gift(user): + medals = [] + if user.task_ctrl['send2wearing-medal']: + medals = await SendGiftTask.fetch_wearing_medal(user) + if not medals: + print('暂未佩戴任何勋章') + if user.task_ctrl['send2medal']: + medals += await UtilsTask.fetch_medals(user, user.task_ctrl['send2medal']) + # print('目前的勋章', medals) + + print('正在投递勋章') + gift_bags = await SendGiftTask.fetch_giftbags(user) + # print(temp) + send_giftbags = [] + for gift in gift_bags: + gift_id = int(gift[0]) + left_time = gift[3] + # 过滤某些特定礼物以及永久礼物 + if (gift_id not in [4, 3, 9, 10]) and left_time is not None: + send_giftbags.append(gift[:3]) + await SendGiftTask.fill_intimacy(user, send_giftbags, medals) + + @staticmethod + async def fill_intimacy(user, gift_bags, medals): + json_rsp = await user.req_s(SendGiftReq.fetch_gift_config, user) + gift_price = {gift['id']: (gift['price'] / 100) for gift in json_rsp['data']} + num_sent = 0 + for room_id, remain_intimacy, medal_name in medals: + filled_intimacy = 0 + for gift in gift_bags: + gift_id, gift_num, bag_id = gift + if (gift_num * gift_price[gift_id] <= remain_intimacy): + num_sent = gift_num + elif remain_intimacy >= gift_price[gift_id]: + num_sent = int(remain_intimacy / gift_price[gift_id]) + else: + continue + gift[1] -= num_sent + score = gift_price[gift_id] * num_sent + await UtilsTask.send_gift(user, room_id, num_sent, bag_id, gift_id) + filled_intimacy += score + remain_intimacy -= score + user.info([f'# 对 {medal_name} 共送出亲密度为{filled_intimacy}的礼物']) + # 过滤掉送光了的礼物包 + return [gift for gift in gift_bags if gift[1]] + + @staticmethod + async def send_gift(user): + await SendGiftTask.send_medal_gift(user) + await SendGiftTask.send_expiring_gift(user) + sleeptime = 21600 + return (0, (sleeptime, sleeptime+30), user.id), + + +class ExchangeSilverCoinTask: + @staticmethod + def target(step): + if step == 0: + return ExchangeSilverCoinTask.silver2coin + return None + + @staticmethod + async def silver2coin(user): + if not user.task_ctrl['silver2coin']: + sleeptime = 21600 + return (0, (sleeptime, sleeptime+30), user.id), + json_rsp = await user.req_s(ExchangeSilverCoinReq.silver2coin_web, user) + user.info([f'# {json_rsp["msg"]}']) + if json_rsp['code'] == 403 and '最多' in json_rsp['msg']: + finish_web = True + else: + finish_web = False + if finish_web: + sleeptime = utils.seconds_until_tomorrow() + 300 + else: + sleeptime = 350 + + return (0, (sleeptime, sleeptime+30), user.id), + diff --git a/tasks/login.py b/tasks/login.py new file mode 100644 index 0000000..0e7b2d4 --- /dev/null +++ b/tasks/login.py @@ -0,0 +1,93 @@ +import base64 +from urllib import parse +import rsa +from reqs.login import LoginReq + + +class LoginTask: + @staticmethod + async def handle_login_status(user): + if not user.is_online(): + return await LoginTask.login(user) + if not (await LoginTask.is_token_usable(user)): + if not (await LoginTask.refresh_token(user)): + return await LoginTask.login(user) + else: + if not (await LoginTask.is_token_usable(user)): + return await LoginTask.login(user) + return True + + async def is_token_usable(user): + json_rsp = await LoginReq.is_token_usable(user) + if not json_rsp['code'] and 'mid' in json_rsp['data']: + user.info(['token有效期检查: 仍有效'], True) + return True + user.info(['token可能过期'], True) + return False + + async def refresh_token(user): + json_rsp = await LoginReq.refresh_token(user) + if not json_rsp['code'] and 'mid' in json_rsp['data']['token_info']: + user.info(['token刷新成功'], True) + data = json_rsp['data'] + access_key = data['token_info']['access_token'] + refresh_token = data['token_info']['refresh_token'] + cookies = data['cookie_info']['cookies'] + list_cookies = [f'{i["name"]}={i["value"]}' for i in cookies] + cookie = ';'.join(list_cookies) + login_data = { + 'csrf': cookies[0]['value'], + 'access_key': access_key, + 'refresh_token': refresh_token, + 'cookie': cookie + } + user.update_login_data(login_data) + return True + return False + + async def login(user): + name = user.name + password = user.password + json_rsp = await LoginReq.fetch_key(user) + data = json_rsp['data'] + key = data['key'] + hash = str(data['hash']) + pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(key.encode()) + hashed_password = base64.b64encode(rsa.encrypt((hash + password).encode('utf-8'), pubkey)) + url_password = parse.quote_plus(hashed_password) + url_name = parse.quote_plus(name) + + json_rsp = await LoginReq.normal_login(user, url_name, url_password) + while json_rsp['code'] == -105: + json_rsp = await LoginReq.captcha_login(user, url_name, url_password) + + 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'] + cookies = data['cookie_info']['cookies'] + list_cookies = [f'{i["name"]}={i["value"]}' for i in cookies] + cookie = ';'.join(list_cookies) + login_data = { + 'csrf': cookies[0]['value'], + 'access_key': access_key, + 'refresh_token': refresh_token, + 'cookie': cookie, + 'uid': cookies[1]['value'] + } + + user.update_login_data(login_data) + user.info(['登陆成功'], True) + return True + else: + login_data = { + 'csrf': f'{json_rsp}', + 'access_key': '', + 'refresh_token': '', + 'cookie': '', + 'uid': 'NULL' + } + # print(dic_saved_session) + user.update_login_data(login_data) + user.info([f'登录失败,错误信息为:{json_rsp}'], True) + return False diff --git a/tasks/main_daily_job.py b/tasks/main_daily_job.py new file mode 100644 index 0000000..c6cb1d4 --- /dev/null +++ b/tasks/main_daily_job.py @@ -0,0 +1,262 @@ +import re +import json +import random +from datetime import datetime +import utils +from reqs.utils import UtilsReq +from reqs.main_daily_job import JudgeCaseReq, BiliMainReq + + +class JudgeCaseTask: + @staticmethod + def target(step): + if step == 0: + return JudgeCaseTask.judge + if step == 1: + return JudgeCaseTask.judge_case + return None + + @staticmethod + async def print_judge_tasks(user): + json_rsp = await user.req_s(JudgeCaseReq.fetch_judged_cases, user) + data = json_rsp['data'] + if data is None: + user.info([f'该用户非风纪委成员'], True) + return + today = datetime.today().date() + sum_cases = 0 + valid_cases = 0 + for case in data: + ts = case['voteTime'] / 1000 + vote_day = datetime.fromtimestamp(ts).date() + if vote_day == today: + sum_cases += 1 + if case['vote'] != 3: + valid_cases += 1 + user.info([f'今日已投票{sum_cases},其中有效票(即非弃权票)为{valid_cases}'], True) + + @staticmethod + def judge_advice(num_judged, pct): + advice = None + if num_judged >= 300: + # 认为这里可能出现了较多分歧,抬一手 + if pct >= 0.4: + advice = 2 + elif pct <= 0.25: + advice = 4 + elif num_judged >= 150: + if pct >= 0.9: + advice = 2 + elif pct <= 0.1: + advice = 4 + elif num_judged >= 50: + if pct >= 0.97: + advice = 2 + elif pct <= 0.03: + advice = 4 + # 抬一手 + if advice is None and num_judged >= 400: + advice = 2 + return advice + + @staticmethod + async def check_case_status(user, case_id): + # 3放弃 + # 2 否 voterule + # 4 删除 votedelete + # 1 封杀 votebreak + text_rsp = await user.req_s(JudgeCaseReq.check_case_status, user, case_id) + result = re.search(r'\((.+)\)', text_rsp).group(1) + json_rsp = json.loads(result) + data = json_rsp['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 + + @staticmethod + async def judge_case(user, case_id, wait_time, fluctuation): + print(f'{case_id} {wait_time} {fluctuation}') + min_pct, max_pct = fluctuation + num_judged, ok_pct = await JudgeCaseTask.check_case_status(user, case_id) + advice = JudgeCaseTask.judge_advice(num_judged, ok_pct) + if num_judged >= 50: + min_pct = min(min_pct, ok_pct) + max_pct = max(max_pct, ok_pct) + print('统计投票波动情况', min_pct, max_pct) + + if advice is not None: + pass + elif wait_time >= 1200: + print('进入二次判定') + # 如果case判定中,波动很小,则表示趋势基本一致 + if 0 <= max_pct - min_pct <= 0.1 and num_judged > 200: + num_judged += 100 + advice0 = JudgeCaseTask.judge_advice(num_judged, max_pct) + advice1 = JudgeCaseTask.judge_advice(num_judged, min_pct) + advice = advice0 if advice0 == advice1 else None + print('二次判定结果', advice) + else: + sleeptime = 180 if num_judged < 300 else 60 + user.info([f'案件{case_id}暂时无法判定,在{sleeptime}后重新尝试'], True) + wait_time += sleeptime + fluctuation = (min_pct, max_pct) + return (1, (sleeptime, sleeptime+5), user.id, case_id, wait_time, fluctuation), + + decision = advice if advice is not None else 3 + dicision_info = '作废票' if decision == 3 else '有效票' + print(f'{case_id}案件的投票决策', decision, dicision_info) + json_rsp = await user.req_s(JudgeCaseReq.judge_case, user, case_id, decision) + print(json_rsp) + if not json_rsp['code']: + print(f'{case_id}案件 投票成功') + else: + print(f'{case_id}案件 投票失败,请反馈作者') + sleeptime = 5 + return (0, (sleeptime, sleeptime+30), user.id), + + @staticmethod + async def judge(user): + json_rsp = await user.req_s(JudgeCaseReq.fetch_case, user) + print(json_rsp) + if not json_rsp['code']: + case_id = json_rsp['data']['id'] + wait_time = 0 + fluctuation = (1, 0) + sleeptime = 0 + return (1, (sleeptime, sleeptime+5), user.id, case_id, wait_time, fluctuation), + else: + print('本次未获取到案件') + sleeptime = 3600 + return (0, (sleeptime, sleeptime+30), user.id), + + +# 这里怀疑登陆硬币没做好!!! +class BiliMainTask: + @staticmethod + def target(step): + if step == 0: + return BiliMainTask.finish_bilimain_tasks + return None + + @staticmethod + async def fetch_bilimain_tasks(user): + json_rsp = await user.req_s(UtilsReq.fetch_bilimain_tasks, user) + data = json_rsp['data'] + login = data['login'] + watch_av = data['watch_av'] + coins_av = data['coins_av'] + share_av = data['share_av'] + print(login, watch_av, coins_av, share_av) + return login, watch_av, coins_av, share_av + + @staticmethod + async def send_coin2video(user, aid, num_sent): + if num_sent not in (1, 2): + return 1 + return False + # 10004 稿件已经被删除 + # 34005 超过,满了 + # -104 不足硬币 + json_rsp = await user.req_s(BiliMainReq.send_coin2video, user, aid, num_sent) + code = json_rsp['code'] + if not code: + print(f'给视频av{aid}投{num_sent}枚硬币成功') + return 0 + else: + print('投币失败', json_rsp) + # -104 硬币不足 -650 用户等级太低 + if code == -104 or code == -102 or code == -650: + return -1 + return 1 + + @staticmethod + async def fetch_top_videos(user): + text_rsp = await user.req_s(BiliMainReq.fetch_top_videos, user) + aids = re.findall(r'(?<=www.bilibili.com/video/av)\d+(?=/)', text_rsp) + if not aids: + user.warn(f'{text_rsp}, aid这里') + # print(aids) + aids = list(set(aids)) + return aids + + @staticmethod + async def fetch_uper_videos(user, uids): + aids = [] + for uid in uids: + json_rsp = await user.req_s(BiliMainReq.fetch_uper_videos, user, uid, 1) + data = json_rsp['data'] + pages = data['pages'] + videos = data['vlist'] + if videos: + aids += [video['aid'] for video in videos] + for page in range(2, pages + 1): + json_rsp = await user.req_s(BiliMainReq.fetch_uper_videos, user, uid, page) + videos = json_rsp['data']['vlist'] + aids += [video['aid'] for video in videos] + print(len(aids), aids[:10]) + return aids + + @staticmethod + async def aid2cid(user, aid): + json_rsp = await user.req_s(BiliMainReq.aid2cid, user, aid) + # 傻逼东西有的aid 404 + if json_rsp is None: + user.warn(f'404检测 视频{aid}') + return None + return json_rsp[0]['cid'] + + @staticmethod + async def heartbeat(user, aid, cid): + print('开始获取视频观看经验') + json_rsp = await user.req_s(BiliMainReq.heartbeat, user, aid, cid) + print('获取视频观看', json_rsp) + + @staticmethod + async def send_coin(user, num_coin, aids): + print('开始赠送硬币') + while num_coin > 0: + aid = random.choice(aids) + result = await BiliMainTask.send_coin2video(user, aid, 1) + if result == -1: + return + elif not result: + num_coin -= 1 + + # 伪造了这个过程,实际没有分享出去 + @staticmethod + async def share_video(user, aid): + print('开始获取视频分享经验') + print(await user.req_s(BiliMainReq.share_video, user, aid)) + + # 后期微调,因为获取fetch_top_videos这个东西可以共享的!!!但是调节起来估计很恶心 + @staticmethod + async def finish_bilimain_tasks(user): + login, watch_av, num, share_av = await BiliMainTask.fetch_bilimain_tasks(user) + if user.task_ctrl['fetchrule'] == 'bilitop': + aids = await BiliMainTask.fetch_top_videos(user) + # print(list_topvideo) + else: + aids = await BiliMainTask.fetch_uper_videos(user, user.task_ctrl['mid']) + while True: + aid = random.choice(aids) + cid = await BiliMainTask.aid2cid(user, aid) + if cid is not None: + break + if (not login) or not watch_av: + await BiliMainTask.heartbeat(user, aid, cid) + if not share_av: + await BiliMainTask.share_video(user, aid) + coin_set = min(user.task_ctrl['givecoin'], 5) + num_coin = coin_set - num / 10 + await BiliMainTask.send_coin(user, num_coin, aids) + # b站傻逼有记录延迟,3点左右成功率高一点 + sleeptime = utils.seconds_until_tomorrow() + 10800 + return (0, (sleeptime, sleeptime+30), user.id), + diff --git a/tasks/storm_raffle_handler.py b/tasks/storm_raffle_handler.py new file mode 100644 index 0000000..511ec8e --- /dev/null +++ b/tasks/storm_raffle_handler.py @@ -0,0 +1,51 @@ +import bili_statistics +from reqs.storm_raffle_handler import StormRaffleHandlerReq +from tasks.utils import UtilsTask + + +class StormRaffleHandlerTask: + @staticmethod + def target(step): + if step == 0: + return StormRaffleHandlerTask.check + if step == 1: + return StormRaffleHandlerTask.join + return None + + # 为了速度,有时不用等room_id验证就参加,置room_id为0,is_normal_room自然会返回固定值true + @staticmethod + async def check(user, room_id, raffle_id=None): + if not await UtilsTask.is_normal_room(user, room_id): + return + if raffle_id is not None: + json_rsp = {'data': {'id': raffle_id}} + else: + json_rsp = await user.req_s(StormRaffleHandlerReq.check, user, room_id) + next_step_settings = [] + data = json_rsp['data'] + if data: + raffle_id = data['id'] + if not bili_statistics.is_raffleid_duplicate(raffle_id): + print('本次获取到的抽奖id为', raffle_id) + next_step_setting = (1, (1, 3), -2, room_id, raffle_id) + next_step_settings.append(next_step_setting) + + next_step_setting = (1, (2, 4), -2, room_id, raffle_id) + next_step_settings.append(next_step_setting) + + bili_statistics.add2raffle_ids(raffle_id) + return next_step_settings + + @staticmethod + async def join(user, room_id, raffle_id): + await UtilsTask.enter_room(user, room_id) + json_rsp = await user.req_s(StormRaffleHandlerReq.join, user, raffle_id) + bili_statistics.add2joined_raffles('节奏风暴(合计)', user.id) + if not json_rsp['code']: + data = json_rsp['data'] + gift_name = data["gift_name"] + gift_num = data["gift_num"] + user.info([f'# 房间{room_id:^9}节奏风暴抽奖结果: {gift_name}X{gift_num}'], True) + bili_statistics.add2results(gift_name, user.id, gift_num) + return + print(json_rsp) diff --git a/tasks/substance_raffle_handler.py b/tasks/substance_raffle_handler.py new file mode 100644 index 0000000..1e692d8 --- /dev/null +++ b/tasks/substance_raffle_handler.py @@ -0,0 +1,51 @@ +from reqs.substance_raffle_handler import SubstanceRaffleHandlerReq +from utils import curr_time + + +class SubstanceRaffleHandlerTask: + @staticmethod + def target(step): + if step == 0: + return SubstanceRaffleHandlerTask.check + if step == 1: + return SubstanceRaffleHandlerTask.join + return None + + # aid 有点类似于roomid + @staticmethod + async def check(user, aid): + json_rsp = await user.req_s(SubstanceRaffleHandlerReq.check, user, aid) + print('id对应code数值为', json_rsp['code'], aid) + blacklist = ['test', 'TEST', '测试', '加密'] + next_step_settings = [] + # -400 不存在 + if not json_rsp['code']: + temp = json_rsp['data']['title'] + if any(word in temp for word in blacklist): + print("检测到疑似钓鱼类测试抽奖,默认不参与,请自行判断抽奖可参与性") + else: + raffles = json_rsp['data']['typeB'] + for num, value in enumerate(raffles): + join_end_time = value['join_end_time'] + join_start_time = value['join_start_time'] + ts = curr_time() + if int(join_end_time) > ts > int(join_start_time): + print('本次获取到的抽奖id为', num, aid) + max_wait = min(60, int(join_end_time) - ts) + next_step_setting = (1, (0, max_wait), -2, aid, num) + next_step_settings.append(next_step_setting) + if ts < int(join_start_time): + print(json_rsp) + return next_step_settings + + @staticmethod + async def join(user, aid, num): + json_rsp = await user.req_s(SubstanceRaffleHandlerReq.join, aid, num) + user.info([f'参与实物抽奖回显:{json_rsp}'], True) + + @staticmethod + async def check_code(user, aid): + json_rsp = await user.req_s(SubstanceRaffleHandlerReq.check, user, aid) + print(aid, json_rsp) + return json_rsp['code'] + diff --git a/tasks/tv_raffle_handler.py b/tasks/tv_raffle_handler.py new file mode 100644 index 0000000..888282f --- /dev/null +++ b/tasks/tv_raffle_handler.py @@ -0,0 +1,74 @@ +import bili_statistics +from reqs.tv_raffle_handler import TvRaffleHandlerReq +from tasks.utils import UtilsTask + + +class TvRaffleHandlerTask: + @staticmethod + def target(step): + if step == 0: + return TvRaffleHandlerTask.check + if step == 1: + return TvRaffleHandlerTask.join + if step == 2: + return TvRaffleHandlerTask.notice + return None + + # 这是superuser做的,做完之后就broadcast + @staticmethod + async def check(user, real_roomid): + if not await UtilsTask.is_normal_room(user, real_roomid): + return + json_response = await user.req_s(TvRaffleHandlerReq.check, user, real_roomid) + # print(json_response['data']['list']) + checklen = json_response['data']['list'] + next_step_settings = [] + for j in checklen: + raffle_id = j['raffleId'] + raffle_type = j['type'] + max_wait = j['time'] - 15 + # 处理一些重复 + if not bili_statistics.is_raffleid_duplicate(raffle_id): + print('本次获取到的抽奖id为', raffle_id) + next_step_setting = (1, (0, max_wait), -2, real_roomid, raffle_id, raffle_type) + next_step_settings.append(next_step_setting) + bili_statistics.add2raffle_ids(raffle_id) + + return next_step_settings + + @staticmethod + async def join(user, real_roomid, raffleid, raffle_type): + # print('参与', raffleid) + await UtilsTask.enter_room(user, real_roomid) + json_response2 = await user.req_s(TvRaffleHandlerReq.join, user, real_roomid, raffleid) + bili_statistics.add2joined_raffles('小电视(合计)', user.id) + user.info([f'参与了房间{real_roomid:^9}的小电视抽奖'], True) + user.info([f'# 小电视抽奖状态: {json_response2["msg"]}']) + # -400不存在 + # -500繁忙 + code = json_response2['code'] + if not code: + return (2, (170, 190), user.id, raffleid, real_roomid), + elif code == -500: + print('# -500繁忙,稍后重试') + return () + elif code == 400: + user.fall_in_jail() + return () + else: + print(json_response2) + return () + + @staticmethod + async def notice(user, raffleid, real_roomid): + json_response = await user.req_s(TvRaffleHandlerReq.notice, user, real_roomid, raffleid) + # print(json_response) + if not json_response['code']: + # {'code': 0, 'msg': '正在抽奖中..', 'message': '正在抽奖中..', 'data': {'gift_id': '-1', 'gift_name': '', 'gift_num': 0, 'gift_from': '', 'gift_type': 0, 'gift_content': '', 'status': 3}} + if json_response['data']['gift_id'] == '-1': + print([f'json_response'], True) + return + elif json_response['data']['gift_id'] != '-1': + data = json_response['data'] + user.info([f'# 房间{real_roomid:^9}小电视抽奖结果: {data["gift_name"]}X{data["gift_num"]}'], True) + bili_statistics.add2results(data['gift_name'], user.id, data['gift_num']) diff --git a/tasks/utils.py b/tasks/utils.py new file mode 100644 index 0000000..9483447 --- /dev/null +++ b/tasks/utils.py @@ -0,0 +1,355 @@ +import random +from operator import itemgetter +import printer +from reqs.utils import UtilsReq +import utils + + +class UtilsTask: + @staticmethod + async def enter_room(user, room_id): + if not room_id: + return + await user.req_s(UtilsReq.post_watching_history, user, room_id) + + async def is_normal_room(user, roomid): + if not roomid: + return True + json_response = await user.req_s(UtilsReq.init_room, user, 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) + return False + else: + printer.info([f'抽奖脚本检测到房间{roomid:^9}为正常房间'], True) + return True + + @staticmethod + async def check_room_state(user, roomid): + json_rsp = await user.req_s(UtilsReq.init_room, user, roomid) + return json_rsp['data']['live_status'] + + @staticmethod + async def get_room_by_area(user, areaid): + # 1 娱乐分区, 2 游戏分区, 3 手游分区, 4 绘画分区 + if areaid == 1: + roomid = 23058 + state = await UtilsTask.check_room_state(user, roomid) + if state == 1: + printer.info([f'{areaid}号弹幕监控选择房间({roomid})'], True) + return roomid + + while True: + json_rsp = await user.req_s(UtilsReq.get_rooms_by_area, user, areaid) + data = json_rsp['data'] + roomid = random.choice(data)['roomid'] + state = await UtilsTask.check_room_state(user, roomid) + if state == 1: + printer.info([f'{areaid}号弹幕监控选择房间({roomid})'], True) + return roomid + + @staticmethod + async def is_ok_as_monitor(user, room_id, area_id): + json_response = await user.req_s(UtilsReq.init_room, user, 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 user.req_s(UtilsReq.get_room_info, user, 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 + + @staticmethod + async def send_gift(user, room_id, num_sent, bag_id, gift_id): + if not num_sent or not room_id: + return + json_rsp = await user.req_s(UtilsReq.init_room, user, room_id) + ruid = json_rsp['data']['uid'] + biz_id = json_rsp['data']['room_id'] + # 200027 不足数目 + json_rsp = await user.req_s(UtilsReq.send_gift, user, gift_id, num_sent, bag_id, ruid, biz_id) + # print(json_rsp) + if not json_rsp['code']: + data = json_rsp['data'] + print(f'# 送给房间{room_id:^9}礼物: {data["gift_name"]}X{data["gift_num"]}') + else: + print("# 错误", json_rsp['msg']) + + async def buy_gift(user, room_id, num_sent, coin_type, gift_id): + if not num_sent or not room_id: + return + json_rsp = await user.req_s(UtilsReq.init_room, user, room_id) + ruid = json_rsp['data']['uid'] + biz_id = json_rsp['data']['room_id'] + # 200027 不足数目 + json_rsp = await user.req_s(UtilsReq.buy_gift, user, gift_id, num_sent, ruid, biz_id, coin_type) + if not json_rsp['code']: + data = json_rsp['data'] + print(f'# 送给房间{room_id:^9}礼物: {data["gift_name"]}X{data["gift_num"]}') + else: + print("# 错误", json_rsp['msg']) + + @staticmethod + async def fetch_giftbags(user): + json_rsp = await user.req_s(UtilsReq.fetch_giftbags, user) + gift_bags = [] + cur_time = json_rsp['data']['time'] + for gift in json_rsp['data']['list']: + bag_id = gift['bag_id'] + gift_id = gift['gift_id'] + gift_num = gift['gift_num'] + gift_name = gift['gift_name'] + expire_at = gift['expire_at'] + left_time = expire_at - cur_time + if not expire_at: + left_days = '+∞'.center(6) + left_time = None + else: + left_days = round(left_time / 86400, 1) + gift_bags.append((bag_id, gift_id, gift_num, gift_name, left_days, left_time)) + return gift_bags + + @staticmethod + async def print_giftbags(user): + gift_bags = await UtilsTask.fetch_giftbags(user) + user.info(['查询可用礼物:']) + for _, _, gift_num, gift_name, left_days, _ in gift_bags: + print(f'# {gift_name:^3}X{gift_num:^4} (在{left_days:^6}天后过期)') + + # medals_wanted [roomid0, roomid1 …] + @staticmethod + async def fetch_medals(user, medals_wanted=None): + json_rsp = await user.req_s(UtilsReq.fetch_medals, user) + # print(json_rsp) + medals = [] + if not json_rsp['code']: + for medal in json_rsp['data']['fansMedalList']: + # 有的房间封禁了 + if 'roomid' in medal: + room_id = medal['roomid'] + remain_intimacy = int(medal['dayLimit']) - int(medal['todayFeed']) + medal_name = medal['medal_name'] + level = medal['level'] + medals.append((room_id, remain_intimacy, medal_name, level)) + + if medals_wanted is not None: + results = [] + for room_id in medals_wanted: + for medal in medals: + if medal[0] == room_id: + results.append(medal[:3]) + break + else: + results = [medal[:3] for medal in sorted(medals, key=itemgetter(3), reverse=True)] + return results + + # 这套对齐策略目前不完全对,而且看起来够恶心的 + # 如果对亲密度同样对齐,会导致输出过长 + @staticmethod + async def print_medals(user): + json_rsp = await user.req_s(UtilsReq.fetch_medals, user) + # 打印队列 + print_queue = [] + print_queue.append('查询勋章信息') + medal_name = utils.adjust_for_chinese('勋章名字', 7) + uname = utils.adjust_for_chinese('用户名字', 12) + intimacy = f'{"INTIMACY":^19}' + today_intimacy = f'{"TODAY_INTIMACY":^14}' + rank = f'{"RANK":^9}' + worn_status = utils.adjust_for_chinese('佩戴状态', 6) + print_queue.append(f'{medal_name} {uname} {intimacy} {today_intimacy} {rank} {worn_status}') + if not json_rsp['code']: + for medal in json_rsp['data']['fansMedalList']: + if 'roomid' in medal: + medal_name = utils.adjust_for_chinese(f'{medal["medal_name"]}|{medal["level"]}', 7) + uname = utils.adjust_for_chinese(medal['anchorInfo']['uname'], 12) + intimacy = f'{medal["intimacy"]:>9}/{medal["next_intimacy"]:<9}' + today_intimacy = f'{medal["todayFeed"]:>6}/{medal["dayLimit"]:<7}' + rank = f'{medal["rank"]:^9}' + org_worn_status = '正在佩戴' if medal['status'] else '目前待机' + worn_status = utils.adjust_for_chinese(org_worn_status, 6) + print_queue.append(f'{medal_name} {uname} {intimacy} {today_intimacy} {rank} {worn_status}') + user.info(print_queue, True) + + @staticmethod + async def print_bilimain_tasks(user): + user.info(['查询用户主站的日常任务情况'], True) + json_rsp = await user.req_s(UtilsReq.fetch_bilimain_tasks, user) + data = json_rsp['data'] + if data['login']: + print('# 主站每日登录任务已完成') + else: + print('# 主站每日登录任务未完成') + if data['watch_av']: + print('# 主站每日观看视频任务已完成') + else: + print('# 主站每日观看视频任务未完成') + print(f'# 主站每日投币 {data["coins_av"]} (这里乘了10,实际硬币个数为显示数目除以10)') + if data['share_av']: + print('# 主站每日分享视频任务已完成') + else: + print('# 主站每日分享视频任务未完成') + + @staticmethod + async def print_livebili_tasks(user): + user.info(['查询用户直播分站的日常任务情况'], True) + json_rsp = await user.req_s(UtilsReq.fetch_livebili_tasks, user) + # print(json_rsp) + if not json_rsp['code']: + data = json_rsp['data'] + print('双端观看直播:') + double_watch_info = data['double_watch_info'] + 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('直播在线宝箱:') + box_info = data['box_info'] + if box_info['status'] == 1: + print('# 该任务已完成') + else: + print('# 该任务未完成') + print(f'## 一共{box_info["max_times"]}次重置次数,当前为第{box_info["freeSilverTimes"]}次第{box_info["type"]}个礼包(每次3个礼包)') + + print('每日签到:') + sign_info = data['sign_info'] + if sign_info['status'] == 1: + print('# 该任务已完成') + else: + print('# 该任务未完成') + if sign_info['signDaysList'] == list(range(1, sign_info['curDay'] + 1)): + print('# 当前全勤') + else: + print('# 出现断签') + + print('直播奖励:') + live_time_info = data['live_time_info'] + if live_time_info['status'] == 1: + print('# 已完成') + else: + print('# 未完成(目前本项目未实现自动完成直播任务)') + + # 这个api似乎是不全的,没有硬币这些 + @staticmethod + async def print_mainbili_userinfo(user): + user.info(['查询用户主站的信息'], True) + json_rsp = await user.req_s(UtilsReq.fetch_bilimain_userinfo, user) + data = json_rsp['data'] + print('# 用户名', data['uname']) + print('# 硬币数', data['coins']) + print('# b币数', data['bCoins']) + 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'# 主站经验值 {current_exp}/{next_exp}') + utils.print_progress(current_exp, next_exp) + + @staticmethod + async def print_livebili_userinfo(user): + user.info(['查询用户直播分站的信息'], True) + json_rsp_pc = await user.req_s(UtilsReq.fetch_livebili_userinfo_pc, user) + json_rsp_ios = await user.req_s(UtilsReq.fetch_livebili_userinfo_ios, user) + if not json_rsp_ios['code']: + gold_ios = json_rsp_ios['data']['gold'] + if not json_rsp_pc['code']: + data = json_rsp_pc['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) + 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) + utils.print_progress(user_intimacy, user_next_intimacy) + print('# 等级榜', user_level_rank) + + @staticmethod + async def print_capsule_info(user): + user.info(['查询用户扭蛋的信息'], True) + json_rsp = await user.req_s(UtilsReq.fetch_capsule_info, user) + if not json_rsp['code']: + data = json_rsp['data'] + if data['colorful']['status']: + print(f'梦幻扭蛋币: {data["colorful"]["coin"]}个') + else: + print('梦幻扭蛋币暂不可用') + if data['normal']['status']: + print(f'普通扭蛋币: {data["normal"]["coin"]}个') + else: + print('普通扭蛋币暂不可用') + + @staticmethod + async def open_capsule(user, num_opened): + if num_opened not in (1, 10, 100): + print('只能输入1或10或100') + return + json_rsp = await user.req_s(UtilsReq.open_capsule, user, num_opened) + if not json_rsp['code']: + for i in json_rsp['data']['text']: + print(i) + + async def get_real_roomid(user, room_id): + json_rsp = await user.req_s(UtilsReq.init_room, user, room_id) + if not json_rsp['code']: + print('查询结果:') + data = json_rsp['data'] + if not data['short_id']: + print('# 此房间无短房号') + else: + print(f'# 短号为:{data["short_id"]}') + print(f'# 真实房间号为:{data["room_id"]}') + return data['room_id'] + # 房间不存在 + elif json_rsp['code'] == 60004: + print(json_rsp['msg']) + + async def send_danmu(user, msg, room_id): + json_rsp = await user.req_s(UtilsReq.send_danmu, user, msg, room_id) + print(json_rsp) diff --git a/user.py b/user.py new file mode 100644 index 0000000..4a9a4d5 --- /dev/null +++ b/user.py @@ -0,0 +1,133 @@ +import copy +import asyncio +import hashlib +import printer +import conf_loader +from web_session import WebSession +import bili_statistics +from user_status import UserStatus +from tasks.login import LoginTask + + +class User: + def __init__(self, id, dict_user, task_ctrl, dict_bili): + self.id = id + self.name = dict_user['username'] + self.password = dict_user['password'] + self.task_ctrl = task_ctrl + self.status = UserStatus(self) + self._bililive_session = None + self._login_session = None + self._other_session = None + # 每个user里面都分享了同一个dict,必须要隔离,否则更新cookie这些的时候会互相覆盖 + self.dict_bili = copy.deepcopy(dict_bili) + self.app_params = f'actionKey={dict_bili["actionKey"]}&appkey={dict_bili["appkey"]}&build={dict_bili["build"]}&device={dict_bili["device"]}&mobi_app={dict_bili["mobi_app"]}&platform={dict_bili["platform"]}' + self.update_login_data(dict_user) + self.list_delay = [] + + def update_login_data(self, login_data): + for i, value in login_data.items(): + self.dict_bili[i] = value + if i == 'cookie': + self.dict_bili['pcheaders']['cookie'] = value + self.dict_bili['appheaders']['cookie'] = value + conf_loader.write_user(login_data, self.id) + + def is_online(self): + return self.dict_bili['pcheaders']['cookie'] and self.dict_bili['appheaders']['cookie'] + + @property + def bililive_session(self): + if self._bililive_session is None: + self._bililive_session = WebSession() + return self._bililive_session + + @property + def login_session(self): + if self._login_session is None: + self._login_session = WebSession() + # print('测试session') + return self._login_session + + @property + def other_session(self): + if self._other_session is None: + self._other_session = WebSession() + return self._other_session + + def info(self, list_msg, tag_time=False, with_userid=False): + if with_userid: + list_msg[0] += f'(用户id:{self.id} 用户名:{self.name})' + printer.info(list_msg, tag_time) + + def warn(self, msg): + printer.warn(f'{msg}, 用户id:{self.id} 用户名:{self.name}') + + def calc_sign(self, str): + str = f'{str}{self.dict_bili["app_secret"]}' + hash = hashlib.md5() + hash.update(str.encode('utf-8')) + sign = hash.hexdigest() + return sign + + async def get_statistic(self): + await asyncio.sleep(0) + self.status.print_status() + bili_statistics.print_statistics(self.id) + + # 保证在线 + async def req_s(self, func, *args): + while True: + # print('网络请求', func, args) + rsp = await func(*args) + # print('请求结果', func, rsp) + # if random.randint(0, 7) in (3, 4) or rsp == 3: + # rsp = 3 + is_online = self.status.check_log_status() + if not is_online: + future = asyncio.Future() + self.list_delay.append(future) + await future + # 未登陆且未处理 + if rsp == 3 and is_online: + self.info([f'判定出现了登陆失败,且未处理'], True) + self.status.logout() + # login + await LoginTask.handle_login_status(self) + # await asyncio.sleep(10) + print(self.list_delay) + self.info([f'已经登陆了'], True) + self.status.login() + for future in self.list_delay: + future.set_result(True) + del self.list_delay[:] + # 未登陆,但已处理 + elif not is_online: + self.info([f'判定出现了登陆失败,已经处理'], True) + else: + return rsp + + async def accept(self, func, *args): + code, sleeptime = self.status.check_status(func) + if not code: + return await func(self, *args) + if code == 2: + return None + if code == 1: + return (-1, (sleeptime, sleeptime+30), self.id, *args), + + def sleep(self): + self.status.sleep() + + def wakeup(self): + self.status.wakeup() + + def fall_in_jail(self): + self.status.go_to_jail() + self.info([f'抽奖脚本检测{self.id}为小黑屋'], True) + + def out_of_jail(self): + self.status.out_of_jail() + + def print_state(self): + return self.state.print_state() diff --git a/user_status.py b/user_status.py new file mode 100644 index 0000000..ecca493 --- /dev/null +++ b/user_status.py @@ -0,0 +1,150 @@ +from datetime import datetime +from tasks.tv_raffle_handler import TvRaffleHandlerTask +from tasks.guard_raffle_handler import GuardRaffleHandlerTask +from tasks.live_daily_job import ( + HeartBeatTask, + RecvHeartGiftTask, + OpenSilverBoxTask, + RecvDailyBagTask, + SignTask, + WatchTvTask, + SignFansGroupsTask, + SendGiftTask, + ExchangeSilverCoinTask, +) +from tasks.main_daily_job import ( + JudgeCaseTask, + BiliMainTask +) + +# 1 延迟操作,返回一个参考延迟范围 +# 2 放弃操作 + + +# 时间状态 +class FreeStatus: + @staticmethod + def check_status(func): + # print('是个自由人') + return 0, None + + +class JailStatus: + dict_jail_status = { + RecvHeartGiftTask.recv_heartgift: 1, + OpenSilverBoxTask.open_silver_box: 1, + + TvRaffleHandlerTask.join: 2, + GuardRaffleHandlerTask.join: 2, + } + + @staticmethod + def check_status(func): + # print('进了监狱') + strategy = JailStatus.dict_jail_status.get(func, 0) + if strategy == 1: + return strategy, 1800 + return strategy, None + + +# 工作状态类 +class DayStatus: + @staticmethod + def check_status(func): + # print("工作,精神百倍") + return 0, None + + +class NightStatus: + dict_night_status = { + HeartBeatTask.heart_beat: 1, + RecvHeartGiftTask.recv_heartgift: 1, + OpenSilverBoxTask.open_silver_box: 1, + RecvDailyBagTask.recv_dailybag: 1, + SignTask.sign: 1, + WatchTvTask.watch_tv: 1, + SignFansGroupsTask.sign_groups: 1, + SendGiftTask.send_gift: 1, + ExchangeSilverCoinTask.silver2coin: 1, + JudgeCaseTask.judge: 1, + BiliMainTask.finish_bilimain_tasks: 1, + + TvRaffleHandlerTask.check: 2, + GuardRaffleHandlerTask.check: 2, + } + + @staticmethod + def check_status(func): + # print("睡觉了") + strategy = NightStatus.dict_night_status.get(func, 0) + if strategy == 1: + now = datetime.now() + # 7点时候 + sleeptime = (7 - now.hour - 1) * 3600 + (59 - now.minute) * 60 + 60 - now.second + return 1, sleeptime + return strategy, None + + +class LoginStatus: + @staticmethod + def check_status(): + # print('因为已经正常登陆') + return True + + +class LogoutStatus: + @staticmethod + def check_status(): + # print('因为未正常登陆') + return False + + +class UserStatus: + def __init__(self, user): + self.time_status = DayStatus + self.work_status = FreeStatus + self.log_status = LoginStatus + self.user = user + + def sleep(self): + # print('{休眠}') + self.time_status = NightStatus + + def wakeup(self): + # print('{起床}') + self.time_status = DayStatus + + def go_to_jail(self): + # print('{入狱}') + self.work_status = JailStatus + + def out_of_jail(self): + # print('{自由}') + self.work_status = FreeStatus + + def logout(self): + # print('{未登陆}') + self.log_status = LogoutStatus + + def login(self): + # print('{已经登陆}') + self.log_status = LoginStatus + + def print_status(self): + work_status = '恭喜中奖' if self.work_status == JailStatus else '自由之身' + time_status = '白天工作' if self.time_status == DayStatus else '夜晚休眠' + self.user.info([f'小黑屋状态: {work_status}'], True) + self.user.info([f'工作状态: {time_status}'], True) + + def check_status(self, func): + code, sleeptime = self.time_status.check_status(func) + # print('初次code', code) + if not code: + code, sleeptime = self.work_status.check_status(func) + # print(code, sleeptime) + return code, sleeptime + + def check_log_status(self): + # print('正在检查', request) + code = self.log_status.check_status() + return code diff --git a/utils.py b/utils.py index ff14a89..93b98e8 100644 --- a/utils.py +++ b/utils.py @@ -1,16 +1,13 @@ -import datetime import time +from datetime import datetime 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.time()) - return tomorrow_start_time - current_time + dt = datetime.now() + return (23 - dt.hour) * 3600 + (59 - dt.minute) * 60 + 60 - dt.second + - -def adjust_for_chinese(str): +def adjust_for_chinese(str, format_control=10): SPACE = '\N{IDEOGRAPHIC SPACE}' EXCLA = '\N{FULLWIDTH EXCLAMATION MARK}' TILDE = '\N{FULLWIDTH TILDE}' @@ -22,5 +19,17 @@ def adjust_for_chinese(str): # build the translation table full = str.maketrans(west, east) str = str.translate(full).rstrip().split('\n') - md = f'{str[0]:^10}' + md = f'{str[0]:^{format_control}}' return md.translate(full) + + +def print_progress(finished_exp, sum_exp, num_sum=30): + num_arrow = int(finished_exp / sum_exp * num_sum) + num_line = num_sum - num_arrow + percent = finished_exp / sum_exp * 100 + process_bar = f'[{">" * num_arrow}{"-" * num_line}] {percent:.2f}%' + print(process_bar) + + +def curr_time(): + return int(time.time()) diff --git a/web_session.py b/web_session.py new file mode 100644 index 0000000..0e7a046 --- /dev/null +++ b/web_session.py @@ -0,0 +1,134 @@ +import sys +import asyncio +import json +import aiohttp +import printer + +sem = asyncio.Semaphore(3) + + +class WebSession: + def __init__(self): + self.var_session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=4)) + + async def __get_json_body(self, rsp, is_login=False): + # json_response = await response.json(content_type=None) + data = await rsp.read() + if not data: + printer.warn(f'json_body出现问题 {data}') + return None + json_body = json.loads(data) + # 之后考虑加入expected_code来约束这个判定 + if isinstance(json_body, dict) and 'code' in json_body: + code = json_body['code'] + if code == 1024: + print('b站炸了,暂停所有请求1.5s后重试,请耐心等待') + await asyncio.sleep(1.5) + return None + elif code == 3 or code == -401 or code == 1003 or code == -101 or code == 401: + print('api提示没有登录') + print(json_body) + if not is_login: + return 3 + else: + return json_body + return json_body + + async def __get_text_body(self, rsp): + text = await rsp.text() + if not text: + printer.warn(f'json_body出现问题 {text}') + return None + return text + + async def __get_binary_body(self, rsp): + return await rsp.read() + + # method 类似于aiohttp里面的对应method,目前只支持GET、POST + # is_login后期移除,json这里应该与expected_code协同 + async def request_json(self, + method, + url, + headers=None, + data=None, + params=None, + is_none_allowed=False, + is_login=False): + async with sem: + i = 0 + while True: + i += 1 + if i >= 10: + printer.warn(url) + try: + async with self.var_session.request(method, url, headers=headers, data=data, params=params) as rsp: + if rsp.status == 200: + json_body = await self.__get_json_body( + rsp, is_login) + if json_body is not None or is_none_allowed: + return json_body + elif rsp.status == 403: + print('403频繁', url) + elif rsp.status == 404: + return None + except: + # print('当前网络不好,正在重试,请反馈开发者!!!!') + print(sys.exc_info()[0], sys.exc_info()[1], url) + continue + + async def request_binary(self, + method, + url, + headers=None, + data=None, + params=None, + is_none_allowed=False): + async with sem: + i = 0 + while True: + i += 1 + if i >= 10: + printer.warn(url) + try: + async with self.var_session.request(method, url, headers=headers, data=data, params=params) as rsp: + if rsp.status == 200: + binary_body = await self.__get_binary_body(rsp) + if binary_body is not None or is_none_allowed: + return binary_body + elif rsp.status == 403: + print('403频繁', url) + elif rsp.status == 404: + return None + except: + # print('当前网络不好,正在重试,请反馈开发者!!!!') + print(sys.exc_info()[0], sys.exc_info()[1], url) + continue + + async def request_text(self, + method, + url, + headers=None, + data=None, + params=None, + is_none_allowed=False): + async with sem: + i = 0 + while True: + i += 1 + if i >= 10: + printer.warn(url) + try: + async with self.var_session.request(method, url, headers=headers, data=data, params=params) as rsp: + if rsp.status == 200: + text_body = await self.__get_text_body(rsp) + if text_body is not None or is_none_allowed: + return text_body + elif rsp.status == 403: + print('403频繁', url) + elif rsp.status == 404: + return None + except: + # print('当前网络不好,正在重试,请反馈开发者!!!!') + print(sys.exc_info()[0], sys.exc_info()[1], url) + continue + diff --git a/webhub/base_web_hub.py b/webhub/base_web_hub.py deleted file mode 100644 index ee35800..0000000 --- a/webhub/base_web_hub.py +++ /dev/null @@ -1,42 +0,0 @@ -import copy -import hashlib -import time -import random - - -class BaseWebHub(): - def __init__(self, id, dict_new, dict_bili): - self.dict_bili = copy.deepcopy(dict_bili) - self.set_status(dict_new) - self.user_id = id - if dict_bili: - self.app_params = f'actionKey={dict_bili["actionKey"]}&appkey={dict_bili["appkey"]}&build={dict_bili["build"]}&device={dict_bili["device"]}&mobi_app={dict_bili["mobi_app"]}&platform={dict_bili["platform"]}' - - def set_status(self, dict_new): - for i, value in dict_new.items(): - self.dict_bili[i] = value - if i == 'cookie': - self.dict_bili['pcheaders']['cookie'] = value - self.dict_bili['appheaders']['cookie'] = value - - def print_status(self): - print(self.dict_bili) - - def cookie_existed(self): - if self.dict_bili['pcheaders']['cookie'] and self.dict_bili['appheaders']['cookie']: - return True - return False - - def calc_sign(self, str): - str = f'{str}{self.dict_bili["app_secret"]}' - hash = hashlib.md5() - hash.update(str.encode('utf-8')) - sign = hash.hexdigest() - return sign - - def CurrentTime(self): - currenttime = int(time.time()) - return str(currenttime) - - def randomint(self): - return ''.join(str(random.randint(0, 9)) for _ in range(17)) diff --git a/webhub/bili_web_hub.py b/webhub/bili_web_hub.py deleted file mode 100644 index 69a3248..0000000 --- a/webhub/bili_web_hub.py +++ /dev/null @@ -1,391 +0,0 @@ -import copy -from webhub.base_web_hub import BaseWebHub -from webhub.web_session import WebSession - - -class BiliWebHub(BaseWebHub): - - def __init__(self, id, dict_new, dict_bili): - self.dict_bili = copy.deepcopy(dict_bili) - self.base_url = 'https://api.live.bilibili.com' - self.set_status(dict_new) - self._bili_session = None - if dict_bili: - self.app_params = f'actionKey={dict_bili["actionKey"]}&appkey={dict_bili["appkey"]}&build={dict_bili["build"]}&device={dict_bili["device"]}&mobi_app={dict_bili["mobi_app"]}&platform={dict_bili["platform"]}' - - @property - def bili_session(self): - if self._bili_session is None: - self._bili_session = WebSession() - # print(0) - return self._bili_session - - async def bili_req_json(self, method, url, headers=None, data=None, params=None): - json_body = await self.bili_session.request_json(method, url, headers=headers, data=data, params=params) - return json_body - - async def playurl(self, cid): - # cid real_roomid - # url = 'http://api.live.bilibili.com/room/v1/Room/playUrl?' - url = f'{self.base_url}/api/playurl?device=phone&platform=ios&scale=3&build=10000&cid={cid}&otype=json&platform=h5' - response = await self.bili_req_json('GET', url) - return response - - async def fetch_capsule(self): - url = f"{self.base_url}/api/ajaxCapsule" - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def open_capsule(self, count): - url = f"{self.base_url}/api/ajaxCapsuleOpen" - data = { - 'type': 'normal', - "count": count, - "csrf_token": self.dict_bili['csrf'] - } - response = await self.bili_req_json('POST', url, data=data, headers=self.dict_bili['pcheaders']) - return response - - # 1:900兑换 - async def doublegain_coin2silver(self): - # url: "/exchange/coin2silver", - data = {'coin': 10} - url = f"{self.base_url}/exchange/coin2silver" - response = await self.bili_req_json('POST', url, data=data, headers=self.dict_bili['pcheaders']) - return response - - async def post_watching_history(self, room_id): - data = { - "room_id": room_id, - "csrf_token": self.dict_bili['csrf'] - } - url = f"{self.base_url}/room/v1/Room/room_entry_action" - response = await self.bili_req_json('POST', url, data=data, headers=self.dict_bili['pcheaders']) - return response - - async def silver2coin_web(self): - url = f"{self.base_url}/pay/v1/Exchange/silver2coin" - data = { - "platform": 'pc', - "csrf_token": self.dict_bili['csrf'] - } - response = await self.bili_req_json('POST', url, headers=self.dict_bili['pcheaders'], data=data) - return response - - async def silver2coin_app(self): - temp_params = f'access_key={self.dict_bili["access_key"]}&{self.app_params}&ts={self.CurrentTime()}' - sign = self.calc_sign(temp_params) - app_url = f"{self.base_url}/AppExchange/silver2coin?{temp_params}&sign={sign}" - response1 = await self.bili_req_json('POST', app_url, headers=self.dict_bili['appheaders']) - return response1 - - async def fetch_fan(self, real_roomid, uid): - url = f'{self.base_url}/rankdb/v1/RoomRank/webMedalRank?roomid={real_roomid}&ruid={uid}' - response = await self.bili_req_json('GET', url) - return response - - async def check_room(self, roomid): - url = f"{self.base_url}/room/v1/Room/room_init?id={roomid}" - response = await self.bili_req_json('GET', url) - return response - - async def fetch_bag_list(self): - url = f"{self.base_url}/gift/v2/gift/bag_list" - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def check_taskinfo(self): - url = f'{self.base_url}/i/api/taskInfo' - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def send_gift_web(self, giftid, giftnum, bagid, ruid, biz_id): - url = f"{self.base_url}/gift/v2/live/bag_send" - data = { - 'uid': self.dict_bili['uid'], - 'gift_id': giftid, - 'ruid': ruid, - 'gift_num': giftnum, - 'bag_id': bagid, - 'platform': 'pc', - 'biz_code': 'live', - 'biz_id': biz_id, - 'rnd': self.CurrentTime(), - 'storm_beat_id': '0', - 'metadata': '', - 'price': '0', - 'csrf_token': self.dict_bili['csrf'] - } - response = await self.bili_req_json('POST', url, headers=self.dict_bili['pcheaders'], data=data) - return response - - async def fetch_user_info(self): - url = f"{self.base_url}/i/api/liveinfo" - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def fetch_user_infor_ios(self): - temp_params = f'access_key={self.dict_bili["access_key"]}&platform=ios' - url = f'{self.base_url}/mobile/getUser?{temp_params}' - response = await self.bili_req_json('GET', url) - return response - - async def fetch_liveuser_info(self, real_roomid): - url = f'{self.base_url}/live_user/v1/UserInfo/get_anchor_in_room?roomid={real_roomid}' - response = await self.bili_req_json('GET', url) - return response - - async def send_danmu_msg_web(self, msg, roomId): - url = f'{self.base_url}/msg/send' - data = { - 'color': '16777215', - 'fontsize': '25', - 'mode': '1', - 'msg': msg, - 'rnd': '0', - 'roomid': int(roomId), - 'csrf_token': self.dict_bili['csrf'], - 'csrf': self.dict_bili['csrf'] - } - - response = await self.bili_req_json('POST', url, headers=self.dict_bili['pcheaders'], data=data) - return response - - async def fetchmedal(self): - url = f'{self.base_url}/i/api/medal?page=1&pageSize=50' - response = await self.bili_req_json('POST', url, headers=self.dict_bili['pcheaders']) - return response - - async def ReqWearingMedal(self): - url = f'{self.base_url}/live_user/v1/UserInfo/get_weared_medal' - data = { - 'uid': self.dict_bili['uid'], - 'csrf_token': '' - } - response = await self.bili_req_json('POST', url, data=data, headers=self.dict_bili['pcheaders']) - return response - - async def ReqTitleInfo(self): - temp_params = f'access_key={self.dict_bili["access_key"]}&{self.app_params}' - sign = self.calc_sign(temp_params) - url = f'{self.base_url}/appUser/myTitleList?{temp_params}&sign={sign}' - response = await self.bili_req_json('GET', url, headers=self.dict_bili['appheaders']) - return response - - async def get_giftlist_of_storm(self, dic): - roomid = dic['roomid'] - get_url = f"{self.base_url}/lottery/v1/Storm/check?roomid={roomid}" - response = await self.bili_req_json('GET', get_url, headers=self.dict_bili['pcheaders']) - return response - - async def get_gift_of_storm(self, id): - storm_url = f'{self.base_url}/lottery/v1/Storm/join' - payload = { - "id": id, - "color": "16777215", - "captcha_token": "", - "captcha_phrase": "", - "token": "", - "csrf_token": self.dict_bili['csrf']} - response1 = await self.bili_req_json('POST', storm_url, data=payload, headers=self.dict_bili['pcheaders']) - return response1 - - async def get_gift_of_events_web(self, room_id, text2, raffleid): - headers = { - **(self.dict_bili['pcheaders']), - 'referer': text2 - } - pc_url = f'{self.base_url}/activity/v1/Raffle/join?roomid={room_id}&raffleId={raffleid}' - pc_response = await self.bili_req_json('GET', pc_url, headers=headers) - - return pc_response - - async def get_gift_of_events_app(self, room_id, text2, raffleid): - headers = { - **(self.dict_bili['appheaders']), - 'referer': text2 - } - temp_params = f'access_key={self.dict_bili["access_key"]}&actionKey={self.dict_bili["actionKey"]}&appkey={self.dict_bili["appkey"]}&build={self.dict_bili["build"]}&device={self.dict_bili["device"]}&event_type=flower_rain-{raffleid}&mobi_app={self.dict_bili["mobi_app"]}&platform={self.dict_bili["platform"]}&room_id={room_id}&ts={self.CurrentTime()}' - # params = temp_params + self.dict_bili['app_secret'] - sign = self.calc_sign(temp_params) - true_url = f'{self.base_url}/YunYing/roomEvent?{temp_params}&sign={sign}' - # response1 = await self.bili_req_json('GET', true_url, params=params, headers=headers) - response1 = await self.bili_req_json('GET', true_url, headers=headers) - return response1 - - async def get_gift_of_TV(self, real_roomid, TV_raffleid): - url = f"{self.base_url}/gift/v3/smalltv/join" - payload = { - "roomid": real_roomid, - "raffleId": TV_raffleid, - "type": "Gift", - "csrf_token": '' - } - - response = await self.bili_req_json('POST', url, data=payload, headers=self.dict_bili['pcheaders']) - return response - - async def get_gift_of_TV_app(self, real_roomid, raffle_id, raffle_type): - url = f"{self.base_url}/gift/v4/smalltv/getAward" - temp_params = f'access_key={self.dict_bili["access_key"]}&{self.app_params}&raffleId={raffle_id}&roomid={real_roomid}&ts={self.CurrentTime()}&type={raffle_type}' - sign = self.calc_sign(temp_params) - payload = f'{temp_params}&sign={sign}' - # print(payload) - response = await self.bili_req_json('POST', url, params=payload, headers=self.dict_bili['appheaders']) - # print(response) - return response - - async def get_gift_of_guard(self, roomid, id): - url = f"{self.base_url}/lottery/v2/Lottery/join" - data = { - 'roomid': roomid, - 'id': id, - 'type': 'guard', - 'csrf_token': self.dict_bili['csrf'] - } - json_rsp = await self.bili_req_json('POST', url, data=data, headers=self.dict_bili['pcheaders']) - return json_rsp - - async def get_giftlist_of_events(self, room_id): - url = f'{self.base_url}/activity/v1/Raffle/check?roomid={room_id}' - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def get_giftlist_of_TV(self, real_roomid): - url = f"{self.base_url}/gift/v3/smalltv/check?roomid={real_roomid}" - response = await self.bili_req_json('GET', url) - return response - - async def get_giftlist_of_guard(self, roomid): - url = f'{self.base_url}/lottery/v1/Lottery/check_guard?roomid={roomid}' - json_rsp = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return json_rsp - - async def get_activity_result(self, activity_roomid, activity_raffleid): - url = f"{self.base_url}/activity/v1/Raffle/notice?roomid={activity_roomid}&raffleId={activity_raffleid}" - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def get_TV_result(self, TV_roomid, TV_raffleid): - url = f"{self.base_url}/gift/v3/smalltv/notice?type=small_tv&raffleId={TV_raffleid}" - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def pcpost_heartbeat(self): - - url = f'{self.base_url}/User/userOnlineHeart' - response = await self.bili_req_json('POST', url, headers=self.dict_bili['pcheaders']) - return response - - # 发送app心跳包 - - async def apppost_heartbeat(self): - - time = self.CurrentTime() - temp_params = f'access_key={self.dict_bili["access_key"]}&{self.app_params}&ts={time}' - sign = self.calc_sign(temp_params) - url = f'{self.base_url}/mobile/userOnlineHeart?{temp_params}&sign={sign}' - payload = {'roomid': 23058, 'scale': 'xhdpi'} - response = await self.bili_req_json('POST', url, data=payload, headers=self.dict_bili['appheaders']) - return response - - # 心跳礼物 - async def heart_gift(self): - url = f"{self.base_url}/gift/v2/live/heart_gift_receive?roomid=3&area_v2_id=34" - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def get_lotterylist(self, i): - url = f"{self.base_url}/lottery/v1/box/getStatus?aid={i}" - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def get_gift_of_lottery(self, i, g): - url1 = f'{self.base_url}/lottery/v1/box/draw?aid={i}&number={g + 1}' - response1 = await self.bili_req_json('GET', url1, headers=self.dict_bili['pcheaders']) - return response1 - - async def get_time_about_silver(self): - time = self.CurrentTime() - temp_params = f'access_key={self.dict_bili["access_key"]}&{self.app_params}&ts={time}' - sign = self.calc_sign(temp_params) - GetTask_url = f'{self.base_url}/mobile/freeSilverCurrentTask?{temp_params}&sign={sign}' - response = await self.bili_req_json('GET', GetTask_url, headers=self.dict_bili['appheaders']) - return response - - async def get_silver(self, timestart, timeend): - time = self.CurrentTime() - temp_params = f'access_key={self.dict_bili["access_key"]}&{self.app_params}&time_end={timeend}&time_start={timestart}&ts={time}' - sign = self.calc_sign(temp_params) - url = f'{self.base_url}/mobile/freeSilverAward?{temp_params}&sign={sign}' - response = await self.bili_req_json('GET', url, headers=self.dict_bili['appheaders']) - return response - - async def get_dailybag(self): - url = f'{self.base_url}/gift/v2/live/receive_daily_bag' - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def get_dosign(self): - url = f'{self.base_url}/sign/doSign' - response = await self.bili_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return response - - async def get_dailytask(self): - url = f'{self.base_url}/activity/v1/task/receive_award' - payload2 = {'task_id': 'double_watch_task'} - response2 = await self.bili_req_json('POST', url, data=payload2, headers=self.dict_bili['appheaders']) - return response2 - - async def gift_list(self): - url = f"{self.base_url}/gift/v3/live/gift_config" - res = await self.bili_req_json('GET', url) - return res - - async def req_realroomid(self, areaid): - url = f'{self.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 self.bili_req_json('GET', url) - return json_rsp - - async def req_room_init(self, roomid): - url = f'{self.base_url}/room/v1/Room/room_init?id={roomid}' - json_rsp = await self.bili_req_json('GET', url) - return json_rsp - - async def ReqRoomInfo(self, roomid): - url = f"{self.base_url}/room/v1/Room/get_info?room_id={roomid}" - res = await self.bili_req_json('GET', url) - return res - - -class HostBiliWebHub(BiliWebHub): - - def __init__(self, id, dict_new, dict_bili, host): - self.dict_bili = copy.deepcopy(dict_bili) - self.set_status(dict_new) - self.user_id = id - self._bili_session = None - if dict_bili: - self.app_params = f'actionKey={dict_bili["actionKey"]}&appkey={dict_bili["appkey"]}&build={dict_bili["build"]}&device={dict_bili["device"]}&mobi_app={dict_bili["mobi_app"]}&platform={dict_bili["platform"]}' - self.host = host - self.base_url = f'http://{self.host.get_host()}' - self.headers_host = {'host': 'api.live.bilibili.com'} - - async def bili_req_json(self, method, url, headers={}, data=None, parama=None): - # print(url) - i = 5 - while True: - i -= 1 - if i < 0: - self.base_url = f'http://{self.host.get_host()}' - list_words = url.split('/') - list_words[2] = self.base_url - url = '/'.join(list_words[2:]) - print('ip切换为', url) - i = 5 - json_body = await self.bili_session.request_json(method, url, headers={**headers, **(self.headers_host)}, data=data, params=parama, is_none_allowed=True) - if json_body is not None: - return json_body - - - diff --git a/webhub/login_web_hub.py b/webhub/login_web_hub.py deleted file mode 100644 index 2cc0e5c..0000000 --- a/webhub/login_web_hub.py +++ /dev/null @@ -1,103 +0,0 @@ -import copy -from PIL import Image -from io import BytesIO -import requests -import base64 -from webhub.base_web_hub import BaseWebHub -from webhub.web_session import WebSession - - -class LoginWebHub(BaseWebHub): - - def __init__(self, id, dict_new, dict_bili): - self.dict_bili = copy.deepcopy(dict_bili) - self.set_status(dict_new) - self.user_id = id - self._login_session = None - if dict_bili: - self.app_params = f'actionKey={dict_bili["actionKey"]}&appkey={dict_bili["appkey"]}&build={dict_bili["build"]}&device={dict_bili["device"]}&mobi_app={dict_bili["mobi_app"]}&platform={dict_bili["platform"]}' - - def cnn_captcha(self, 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(self, content): - img = Image.open(BytesIO(content)) - # img.thumbnail(size) - img.show() - captcha = input('手动输入验证码') - return captcha - - @property - def login_session(self): - if self._login_session is None: - self._login_session = WebSession() - # print(0) - return self._login_session - - async def login_req_json(self, method, url, headers=None, data=None, params=None): - json_body = await self.login_session.request_json(method, url, headers=headers, data=data, params=params, is_login=True) - return json_body - - async def login_req_binary(self, method, url, headers=None, data=None, params=None): - binary_body = await self.login_session.request_binary(method, url, headers=headers, data=data, params=params) - return binary_body - - async def logout(self): - url = 'https://passport.bilibili.com/login?act=exit' - json_rsp = await self.login_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return json_rsp - - async def fetch_key(self): - url = 'https://passport.bilibili.com/api/oauth2/getKey' - temp_params = f'appkey={self.dict_bili["appkey"]}' - sign = self.calc_sign(temp_params) - params = {'appkey': self.dict_bili['appkey'], 'sign': sign} - json_rsp = await self.login_req_json('POST', url, data=params) - return json_rsp - - async def normal_login(self, username, password): - url = "https://passport.bilibili.com/api/v2/oauth2/login" - temp_params = f'appkey={self.dict_bili["appkey"]}&password={password}&username={username}' - sign = self.calc_sign(temp_params) - payload = f'appkey={self.dict_bili["appkey"]}&password={password}&username={username}&sign={sign}' - json_rsp = await self.login_req_json('POST', url, params=payload) - return json_rsp - - async def captcha_login(self, username, password): - url = "https://passport.bilibili.com/captcha" - binary_rsp = await self.login_req_binary('GET', url) - # print(binary_rsp) - - captcha = self.cnn_captcha(binary_rsp) - temp_params = f'actionKey={self.dict_bili["actionKey"]}&appkey={self.dict_bili["appkey"]}&build={self.dict_bili["build"]}&captcha={captcha}&device={self.dict_bili["device"]}&mobi_app={self.dict_bili["mobi_app"]}&password={password}&platform={self.dict_bili["platform"]}&username={username}' - sign = self.calc_sign(temp_params) - payload = f'{temp_params}&sign={sign}' - url = "https://passport.bilibili.com/api/v2/oauth2/login" - json_rsp = await self.login_req_json('POST', url, params=payload) - return json_rsp - - async def check_token(self): - list_url = f'access_key={self.dict_bili["access_key"]}&{self.app_params}&ts={self.CurrentTime()}' - list_cookie = self.dict_bili['cookie'].split(';') - params = ('&'.join(sorted(list_url.split('&') + list_cookie))) - sign = self.calc_sign(params) - true_url = f'https://passport.bilibili.com/api/v2/oauth2/info?{params}&sign={sign}' - json_rsp = await self.login_req_json('GET', true_url, headers=self.dict_bili['appheaders']) - return json_rsp - - async def refresh_token(self): - list_url = f'access_key={self.dict_bili["access_key"]}&access_token={self.dict_bili["access_key"]}&{self.app_params}&refresh_token={self.dict_bili["refresh_token"]}&ts={self.CurrentTime()}' - list_cookie = self.dict_bili['cookie'].split(';') - params = ('&'.join(sorted(list_url.split('&') + list_cookie))) - sign = self.calc_sign(params) - payload = f'{params}&sign={sign}' - # print(payload) - url = f'https://passport.bilibili.com/api/v2/oauth2/refresh_token' - json_rsp = await self.login_req_json('POST', url, headers=self.dict_bili['appheaders'], params=payload) - return json_rsp diff --git a/webhub/other_web_hub.py b/webhub/other_web_hub.py deleted file mode 100644 index 723cb24..0000000 --- a/webhub/other_web_hub.py +++ /dev/null @@ -1,142 +0,0 @@ -import copy -from webhub.base_web_hub import BaseWebHub -from webhub.web_session import WebSession - - -class OtherWebHub(BaseWebHub): - - def __init__(self, id, dict_new, dict_bili): - self.dict_bili = copy.deepcopy(dict_bili) - self.set_status(dict_new) - self.user_id = id - self._other_session = None - if dict_bili: - self.app_params = f'actionKey={dict_bili["actionKey"]}&appkey={dict_bili["appkey"]}&build={dict_bili["build"]}&device={dict_bili["device"]}&mobi_app={dict_bili["mobi_app"]}&platform={dict_bili["platform"]}' - - @property - def other_session(self): - if self._other_session is None: - self._other_session = WebSession() - # print(0) - return self._other_session - - async def other_req_json(self, method, url, headers=None, data=None, params=None): - json_body = await self.other_session.request_json(method, url, headers=headers, data=data, params=params) - return json_body - - async def other_req_text(self, method, url, headers=None, data=None, params=None): - text_body = await self.other_session.request_text(method, url, headers=headers, data=data, params=params) - return text_body - - async def other_req_binary(self, method, url, headers=None, data=None, params=None): - binary_body = await self.other_session.request_binary(method, url, headers=headers, data=data, params=params) - return binary_body - - async def search_liveuser(self, name): - search_url = f'https://search.bilibili.com/api/search?search_type=live_user&keyword={name}&page=1' - json_rsp = await self.other_req_json('GET', search_url) - return json_rsp - - async def search_biliuser(self, name): - search_url = f"https://search.bilibili.com/api/search?search_type=bili_user&keyword={name}" - json_rsp = await self.other_req_json('GET', search_url) - return json_rsp - - async def load_img(self, url): - return await self.other_req_binary('GET', url) - - async def get_grouplist(self): - url = "https://api.vc.bilibili.com/link_group/v1/member/my_groups" - json_rsp = await self.other_req_json('GET', url, headers=self.dict_bili['pcheaders']) - return json_rsp - - async def assign_group(self, i1, i2): - temp_params = f'access_key={self.dict_bili["access_key"]}&actionKey={self.dict_bili["actionKey"]}&appkey={self.dict_bili["appkey"]}&build={self.dict_bili["build"]}&device={self.dict_bili["device"]}&group_id={i1}&mobi_app={self.dict_bili["mobi_app"]}&owner_id={i2}&platform={self.dict_bili["platform"]}&ts={self.CurrentTime()}' - sign = self.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 self.other_req_json('GET', url, headers=self.dict_bili['appheaders']) - return json_rsp - - async def ReqGiveCoin2Av(self, video_id, num): - url = 'https://api.bilibili.com/x/web-interface/coin/add' - pcheaders = { - **(self.dict_bili['pcheaders']), - 'referer': f'https://www.bilibili.com/video/av{video_id}' - } - data = { - 'aid': video_id, - 'multiply': num, - 'cross_domain': 'true', - 'csrf': self.dict_bili['csrf'] - } - json_rsp = await self.other_req_json('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.dict_bili['uid'], 'csrf': self.dict_bili['csrf'], - 'played_time': 0, 'realtime': 0, - 'start_ts': self.CurrentTime(), 'type': 3, 'dt': 2, 'play_type': 1} - json_rsp = await self.other_req_json('POST', url, data=data, headers=self.dict_bili['pcheaders']) - return json_rsp - - async def ReqMasterInfo(self): - url = 'https://account.bilibili.com/home/reward' - json_rsp = await self.other_req_json('GET', url, headers=self.dict_bili['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_req_json('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.dict_bili['csrf']} - json_rsp = await self.other_req_json('POST', url, data=data, headers=self.dict_bili['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_req_json('GET', url) - return json_rsp - - async def req_fetch_av(self): - text_tsp = await self.other_req_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": self.dict_bili['csrf'] - } - json_rsp = await self.other_req_json('POST', url, headers=self.dict_bili['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": self.dict_bili['csrf'] - } - json_rsp = await self.other_req_json('POST', url, headers=self.dict_bili['pcheaders'], data=payload) - return json_rsp - - async def req_check_voted(self, id): - headers = { - **(self.dict_bili['pcheaders']), - 'Referer': f'https://www.bilibili.com/judgement/vote/{id}', - } - url = f'https://api.bilibili.com/x/credit/jury/juryCase?jsonp=jsonp&callback=jQuery1720{self.randomint()}_{self.CurrentTime()}&cid={id}&_={self.CurrentTime()}' - text_rsp = await self.other_req_text('GET', url, headers=headers) - # print(text_rsp) - return text_rsp - - diff --git a/webhub/web_hub.py b/webhub/web_hub.py deleted file mode 100644 index 417f79c..0000000 --- a/webhub/web_hub.py +++ /dev/null @@ -1,36 +0,0 @@ -import copy -from webhub.bili_web_hub import BiliWebHub, HostBiliWebHub -from webhub.login_web_hub import LoginWebHub -from webhub.other_web_hub import OtherWebHub - - -class WebHub(BiliWebHub, LoginWebHub, OtherWebHub): - def __init__(self, id, dict_new, dict_bili): - self.dict_bili = copy.deepcopy(dict_bili) - self.base_url = 'https://api.live.bilibili.com' - self.set_status(dict_new) - self.user_id = id - self._bili_session = None - self._other_session = None - self._login_session = None - if dict_bili: - self.app_params = f'actionKey={dict_bili["actionKey"]}&appkey={dict_bili["appkey"]}&build={dict_bili["build"]}&device={dict_bili["device"]}&mobi_app={dict_bili["mobi_app"]}&platform={dict_bili["platform"]}' - - -class HostWebHub(HostBiliWebHub, LoginWebHub, OtherWebHub): - def __init__(self, id, dict_new, dict_bili, host): - self.dict_bili = copy.deepcopy(dict_bili) - self.set_status(dict_new) - self.user_id = id - self._bili_session = None - self._other_session = None - self._login_session = None - if dict_bili: - self.app_params = f'actionKey={dict_bili["actionKey"]}&appkey={dict_bili["appkey"]}&build={dict_bili["build"]}&device={dict_bili["device"]}&mobi_app={dict_bili["mobi_app"]}&platform={dict_bili["platform"]}' - self.host = host - self.base_url = f'http://{self.host.get_host()}' - self.headers_host = {'host': 'api.live.bilibili.com'} - - - - diff --git a/webhub/web_session.py b/webhub/web_session.py deleted file mode 100644 index dbf7d57..0000000 --- a/webhub/web_session.py +++ /dev/null @@ -1,98 +0,0 @@ -import sys -import asyncio -import json -import aiohttp - - -class WebSession: - def __init__(self): - self.var_session = aiohttp.ClientSession() - - async def __get_json_body(self, rsp, url, is_login=False): - if rsp.status == 200: - # json_response = await response.json(content_type=None) - data = await rsp.read() - if not data: - return None - json_body = json.loads(data) - # 之后考虑加入expected_code来约束这个判定 - if isinstance(json_body, dict) and 'code' in json_body: - code = json_body['code'] - if code == 1024: - print('b站炸了,暂停所有请求1.5s后重试,请耐心等待') - await asyncio.sleep(1.5) - return None - elif code == 3 or code == -401 or code == 1003 or code == -101: - print('api提示没有登录') - print(json_body) - if not is_login: - return 3 - else: - return json_body - return json_body - elif rsp.status == 403: - print('403频繁', url) - return None - - async def __get_text_body(self, rsp, url): - if rsp.status == 200: - return await rsp.text() - elif rsp.status == 403: - print('403频繁', url) - return None - - async def __get_binary_body(self, rsp, url): - if rsp.status == 200: - return await rsp.read() - elif rsp.status == 403: - print('403频繁', url) - return None - - # method 类似于aiohttp里面的对应method,目前只支持GET、POST - # is_login后期移除,json这里应该与expected_code协同 - async def request_json(self, method, url, headers=None, - data=None, params=None, is_none_allowed=False, - is_login=False): - while True: - try: - async with self.var_session.request(method, url, - headers=headers, data=data, - params=params) as response: - json_body = await self.__get_json_body(response, url, is_login) - if json_body is not None or is_none_allowed: - return json_body - except: - # print('当前网络不好,正在重试,请反馈开发者!!!!') - print(sys.exc_info()[0], sys.exc_info()[1], url) - continue - - async def request_binary(self, method, url, headers=None, - data=None, params=None, is_none_allowed=False): - while True: - try: - async with self.var_session.request(method, url, - headers=headers, data=data, - params=params) as response: - binary_body = await self.__get_binary_body(response, url) - if binary_body is not None or is_none_allowed: - return binary_body - except: - # print('当前网络不好,正在重试,请反馈开发者!!!!') - print(sys.exc_info()[0], sys.exc_info()[1], url) - continue - - async def request_text(self, method, url, headers=None, - data=None, params=None, is_none_allowed=False): - while True: - try: - async with self.var_session.request(method, url, - headers=headers, data=data, - params=params) as response: - text_body = await self.__get_text_body(response, url) - if text_body is not None or is_none_allowed: - return text_body - except: - # print('当前网络不好,正在重试,请反馈开发者!!!!') - print(sys.exc_info()[0], sys.exc_info()[1], url) - continue -