├── .gitignore ├── LICENSE ├── PROTOCOL.md ├── README.md ├── blive ├── __init__.py ├── core.py ├── eeframework.py ├── framework.py └── msg.py ├── example ├── app.py ├── multi_room.py └── with_fastapi.py ├── poetry.lock └── pyproject.toml /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | .vscode 3 | **/__pycache__ 4 | dist 5 | build 6 | blive.egg-info 7 | test.py 8 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 LinFeng Yu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PROTOCOL.md: -------------------------------------------------------------------------------- 1 | # B 站直播弹幕 websocket 协议分析 2 | 3 | ## 包格式 4 | 5 | ```txt 6 | ____________________________________________________________________________ 7 | | | | | | | 8 | | package_size | header_size | protocol_version | operation | sequence_id | 9 | |______________|_____________|__________________|____________|_____________| 10 | | | 11 | | data | 12 | | | 13 | |__________________________________________________________________________| 14 | ``` 15 | 16 | 包为 byte 数据,由头部和数据组成,字节序均为大端模式 17 | 18 | 头部长度为 16 19 | 20 | | 偏移量 | 长度 | 含义 | 21 | | ------ | ---- | ------------------------- | 22 | | 0 | 4 | 包总大小 package_size | 23 | | 4 | 2 | 头部大小 header_size | 24 | | 6 | 2 | 协议版本 protocol_version | 25 | | 8 | 4 | 操作码 operation | 26 | | 12 | 4 | 包序列 sequence_id | 27 | 28 | 操作码含义 29 | 30 | | 操作码 | 含义 | 31 | | ------ | --------------------------------------------------- | 32 | | 2 | 心跳 HEARTBEAT (标记该包为心跳包) | 33 | | 3 | 心跳回应 HEARTBEAT_REPLY (有时候带着人气值数据返回) | 34 | | 5 | 消息 NOTIFY (B 站的弹幕或业务消息都属于这个操作码) | 35 | | 7 | 认证 AUTH (标记该包为认证包) | 36 | | 8 | 认证回复 AUTH_REPLY | 37 | 38 | 协议版本 39 | 40 | | 协议版本 | 含义 | 41 | | -------- | ----------------------- | 42 | | 0 | NORMAL 未压缩的正常消息 | 43 | | 1 | HEARTBEAT 心跳 | 44 | | 2 | DEFLATE zlib 压缩包 | 45 | | 3 | BROTLI brotil 压缩包 | 46 | 47 | ## 连接建立流程 48 | 49 | 1. 根据直播间 id 得到 websocket 连接地址 50 | 51 | B 站直播间 id 分短 id 和真正的 id,如 510,605,1314,7777 等都属于短 id,需要请求 52 | 53 | `GET https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=房间号` 54 | 55 | 得到真正的房间号,再次请求 56 | 57 | `GET https://api.live.bilibili.com/room/v1/Danmu/getConf?room_id=真正的房间号&platform=pc&player=web` 58 | 59 | 系统会分配 3 个 websocket 连接地址 (负载均衡考虑) 和 连接 token,按照 `wss://{host}:{wss_port}/sub` (TLS WS 连接) 或 `ws://{host}:{ws_port}/sub` (WS 连接格式) 的格式拼接,即可得到 websocket 连接地址 60 | 61 | 2. 建立连接后,发送认证包 62 | 63 | 建立连接后需要立即发送认证包,否则服务器会断开连接 64 | 65 | 认证包数据载荷为 json 格式的字符串,内容如下,和头部拼接时候需要 使用 utf-8 编码转化为 bytes 66 | 67 | ```json 68 | { 69 | "uid": 0, // 用户id,0 代表游客 70 | "roomid": 123, //你要收取弹幕的房间号 71 | "protover": 3, //后面通信要使用的协议版本,主要影响处理粘包时的解码选择,选3代表后面粘包使用 brotil 压缩, 72 | "platform": "web", // 平台选择web端 73 | "type": 2, //不明确,填2 74 | "clientver": "1.4.3", //客户端版本,填1.4.3 75 | "key": "your token" //填写上一步系统给的token值 76 | } 77 | ``` 78 | 79 | 头部操作码选择 7 (AUTH 认证) ,版本为 0 (NORMAL 未压缩的消息), sequence_id 填 1,包大小和头部大小请自行计算填写 80 | 81 | 3. 定时发送心跳包 82 | 83 | B 站服务器设置的心跳间隔约为 70s 左右,所以连接建立后每隔 30s 发送一次心跳维持连接基本稳妥。心跳包内容随意填写无影响,头部操作码选择 2 (HEARTBEAT 心跳), 版本选择 0 (NORMAL 未压缩的消息) 84 | 85 | ## 收到包的消息处理 86 | 87 | 服务器推送的包只会有 3 种操作码,分别为 3(心跳回应),5(消息),8(认证回复),所以我们只需要对这三种包进行处理 88 | 89 | - ### 心跳回应 90 | 91 | 心跳回应数据都是未压缩的,所以可以跳过协议判断,直接 `data[16+4:]`截取有效载荷再使用 utf-8 编码转化为字符串即可,16 是头部长度,+4 是因为数据段前面还有 4 位无效数据?(含义不明,不知道为什么有),直接去掉 92 | 93 | - ### 认证回复 94 | 95 | 认证回复为发送认证包后收到的回复,数据包无压缩,直接 `data[16:]`截取有效载荷再使用 utf-8 编码转化为字符串即可 96 | 97 | - ### 消息 98 | 99 | 首先说明,B 站对 消息 这一数据包出于服务器效率考虑会存在粘包的情况(目前的情况是一定会有粘包的存在),所以在编写处理代码时无可避免要处理这一情况,并且在认证(AUTH)包发送阶段选择的 协议版本 的值会在这一阶段产生影响,如果在认证时选择 0 (NORMAL 未压缩的消息) 或者 1 (HEARTBEAT),则默认服务器在粘包使用 zlib 压缩多个包,若选择 3(Brotil 压缩),则会使用 Brotil 压缩多个包。首先说明服务端的粘包逻辑,这有利于编写解包代码 100 | 101 | - 服务器正常打包每一个数据包 102 | 103 | ```txt 104 | ---------- 105 | | header | 106 | |--------| 107 | | | 108 | | data | 109 | | | 110 | ---------- 111 | ---------- 112 | | header | 113 | |--------| 114 | | | 115 | | data | 116 | | | 117 | ---------- 118 | 119 | ``` 120 | 121 | - 服务器发现包太多,或者单个消息包太大,都会使用认证期选择的压缩协议压缩数据包,并再套上一个包头,协议版本字段写明使用的压缩协议 122 | 123 | ```txt 124 | ---------------- 125 | | header | 126 | ---------------- 127 | | ---------- | 128 | | | header | | 129 | | |--------| | 130 | | | | | 131 | | | data | | 132 | | | | | 133 | | ---------- | 134 | | ---------- | 135 | | | header | | 136 | | |--------| | 137 | | | | | 138 | | | data | | 139 | | | | | 140 | | ---------- | 141 | ---------------- 142 | ``` 143 | 144 | 所以判断是否粘贴包的逻辑为 145 | 146 | ```txt 147 | --------->说明数据载荷为多个包粘贴或单个包太大---->丢弃头部,使用对应压缩协议解压数据段,得到无缝拼接的包数据 148 | / 然后对数据进行拆包提取数据 149 | / 150 | zlib/brotil压缩 151 | / 152 | 收到数据----->判断头部协议版本 153 | \ 154 | 正常消息 155 | \ 156 | -------->说明数据载荷为单个数据---->直接提取数据 157 | 158 | ``` 159 | 160 | 拆包逻辑的主要思想是:首先读取头部信息,计算数据长度是否大于头部声明的数据包长度。如果数据长度大于头部声明的数据长度,则按声明的数据长度截取数据,取出第一个包,然后相同逻辑判断后面的数据,代码实现请参考源代码 blive/core.py `BWS_MsgPackage`类的`unpack`方法实现 161 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # B 站弹幕监听框架 2 | 3 | ## 特点 4 | 5 | - 简单,只需房间号即可监听 6 | - 异步,io 不阻塞,及时获取消息 7 | 8 | ## B 站直播弹幕 websocket 协议分析 9 | 10 | [PROTOCOL 分析](./PROTOCOL.md) 11 | 12 | ## 快速开始 13 | 14 | 1. 安装 15 | 16 | `pip install blive` 17 | 18 | 2. 创建 app 19 | 20 | ```python 21 | from blive import BLiver 22 | 23 | app = BLiver(123) #123为房间号 24 | ``` 25 | 26 | 3. 创建处理器 27 | 28 | ```python 29 | from blive import BLiver, Events, BLiverCtx 30 | from blive.msg import DanMuMsg 31 | 32 | app = BLiver(123) 33 | 34 | # 标记该方法监听弹幕消息,更多消息类型请参考 Events 类源代码 35 | @app.on(Events.DANMU_MSG) 36 | async def listen_danmu(ctx: BLiverCtx): 37 | danmu = DanMuMsg(ctx.body) #ctx.body 套上相应的消息操作类即可得到消息的基本内容,也可直接操作 ctx.body 38 | print(danmu.content) 39 | print(danmu.sender) 40 | print(danmu.timestamp) 41 | ``` 42 | 43 | 4. 运行 44 | 45 | ```python 46 | 47 | from blive import BLiver, Events, BLiverCtx 48 | from blive.msg import DanMuMsg 49 | 50 | app = BLiver(123) 51 | 52 | @app.on(Events.DANMU_MSG) 53 | async def listen_danmu(ctx: BLiverCtx): 54 | danmu = DanMuMsg(ctx.body) 55 | print(danmu.content) 56 | print(danmu.sender) 57 | print(danmu.timestamp) 58 | 59 | app.run() # 运行app! 60 | 61 | ``` 62 | 63 | ## 同时监听多个直播间 64 | 65 | ```python 66 | import asyncio 67 | from blive import BLiver, Events, BLiverCtx 68 | from blive.msg import DanMuMsg 69 | 70 | 71 | # 定义弹幕事件handler 72 | async def listen(ctx: BLiverCtx): 73 | danmu = DanMuMsg(ctx.body) 74 | print( 75 | f'\n{danmu.sender.name} ({danmu.sender.medal.medal_name}:{danmu.sender.medal.medal_level}): "{danmu.content}"\n' 76 | ) 77 | 78 | 79 | async def main(): 80 | # 两个直播间 81 | ke = BLiver(605) 82 | azi = BLiver(510) 83 | 84 | # 注册handler 85 | ke.on(Events.DANMU_MSG, listen) 86 | azi.on(Events.DANMU_MSG, listen) 87 | 88 | # 以异步task的形式运行 89 | task1 = ke.run_as_task() 90 | task2 = azi.run_as_task() 91 | 92 | # await 两个任务 93 | await asyncio.gather(*[task1, task2]) 94 | 95 | 96 | if __name__ == "__main__": 97 | loop = asyncio.get_event_loop() 98 | loop.run_until_complete(main()) 99 | ``` 100 | 101 | ## 作为协议解析工具在其他地方使用(伪代码) 102 | 103 | ```python 104 | from blive.core import BWS_MsgPackage 105 | 106 | packman = BWS_MsgPackage() # 实例化一个消息包处理器 107 | 108 | while True: 109 | data = ws.receive() # 当收到消息时 110 | msg = packman.unpack(data) # 使用packman解析消息,返回一个形如 [(header,body), (header,body), ... ] 数组 111 | print(msg) 112 | ``` 113 | 114 | ## 与 fastapi (其他asyncio生态框架) 配合使用 115 | 116 | ```python 117 | from fastapi import FastAPI 118 | from blive import BLiver,Events 119 | from blive.msg import DanMuMsg 120 | 121 | app = FastAPI() 122 | 123 | BLIVER_POOL = {} 124 | 125 | 126 | # 定义弹幕事件handler 127 | async def handler(ctx): 128 | danmu = DanMuMsg(ctx.body) 129 | print( 130 | f'\n{danmu.sender.name} ({danmu.sender.medal.medal_name}:{danmu.sender.medal.medal_level}): "{danmu.content}"\n' 131 | ) 132 | 133 | def create_bliver(roomid): 134 | b = BLiver(roomid) 135 | b.on(Events.DANMU_MSG,handler) 136 | return b 137 | 138 | 139 | @app.get("/create") 140 | async def create_new_bliver(roomid:int): 141 | room = BLIVER_POOL.get(roomid,None) 142 | if not room: 143 | b = create_bliver(roomid) 144 | BLIVER_POOL[roomid] = b.run_as_task() # 启动监听 145 | return {"msg":"创建一个新直播间弹幕监听成功"} 146 | 147 | 148 | @app.get("/del") 149 | async def rm_bliver(roomid:int): 150 | room = BLIVER_POOL.get(roomid,None) 151 | if room: 152 | room.cancel() 153 | BLIVER_POOL.pop(roomid) 154 | return {"msg":"移除直播间弹幕监听成功"} 155 | 156 | 157 | @app.get("/show") 158 | async def show(): 159 | return list(BLIVER_POOL.keys()) 160 | ``` 161 | 162 | ## 项目简介 163 | 164 | - blive 文件夹为框架代码 165 | 166 | - core.py 为B站ws直播聊天室协议包处理的核心代码 167 | 168 | - eeframework.py 为框架代码 169 | 170 | - msg.py 为消息操作类代码 171 | 172 | - example/app.py 173 | 以框架形式运行例子 174 | 175 | - example/multi_room.py 176 | 同时监听多个直播间的实现 177 | 178 | - example/with_fastapi.py 179 | 与fastapi 配合使用的例子 180 | 181 | 182 | ## TODO 183 | 184 | - 更多的消息操作类(欢迎各位提pr) 185 | - 尝试加入中间件架构(目前感觉需求不大) 186 | -------------------------------------------------------------------------------- /blive/__init__.py: -------------------------------------------------------------------------------- 1 | from .eeframework import * 2 | from .core import * 3 | from .msg import * -------------------------------------------------------------------------------- /blive/core.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | import json 3 | from random import randint 4 | import struct 5 | import enum 6 | import brotli 7 | import zlib 8 | from aiohttp import ClientSession 9 | 10 | 11 | async def get_blive_ws_url(roomid,aio_session:ClientSession,ssl=True, platform="pc", player="web"): 12 | async with aio_session.get( 13 | f"https://api.live.bilibili.com/room/v1/Danmu/getConf", 14 | params={"room_id": roomid, "platform": platform, "player": player}, 15 | ) as resp: 16 | data = await resp.json() 17 | lens = len(data["data"]["host_server_list"]) 18 | url_obj = data["data"]["host_server_list"][randint(0, lens - 1)] 19 | if ssl: 20 | url = f"wss://{url_obj['host']}:{url_obj['wss_port']}/sub" 21 | else: 22 | url = f"ws://{url_obj['host']}:{url_obj['ws_port']}/sub" 23 | return url, data["data"]["token"] 24 | 25 | 26 | async def get_blive_room_info(roomid,aio_session:ClientSession): 27 | """ 28 | 得到b站直播间id,(短id不是真实的id) 29 | 30 | Return: true_room_id,up_name 31 | """ 32 | async with aio_session.get( 33 | "https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom", 34 | params={"room_id": roomid}, 35 | ) as resp: 36 | data = await resp.json() 37 | return ( 38 | data["data"]["room_info"]["room_id"], 39 | data["data"]["anchor_info"]["base_info"]["uname"], 40 | ) 41 | 42 | 43 | def certification(roomid, token, uid=0, protover=1, platform="web"): 44 | return { 45 | "uid": uid, 46 | "roomid": roomid, 47 | "protover": protover, 48 | "platform": platform, 49 | "type": 2, 50 | "clientver": "1.4.3", 51 | "key": token, 52 | } 53 | 54 | 55 | def heartbeat(): 56 | return {} 57 | 58 | 59 | class AuthReplyCode(enum.IntEnum): 60 | OK = 0 61 | TOKEN_ERROR = -101 62 | 63 | 64 | # WS_BODY_PROTOCOL_VERSION 65 | class ProtocolVersion(enum.IntEnum): 66 | NORMAL = 0 # 未压缩 67 | HEARTBEAT = 1 # 心跳 68 | DEFLATE = 2 # zlib压缩 69 | BROTLI = 3 # brotil 压缩 70 | 71 | 72 | class Operation(enum.IntEnum): 73 | HEARTBEAT = 2 # 心跳 74 | HEARTBEAT_REPLY = 3 # 心跳回应 75 | NOTIFY = 5 # 通知 76 | AUTH = 7 # # 认证 77 | AUTH_REPLY = 8 # 认证回应 78 | 79 | 80 | PackageHeader = namedtuple( 81 | "PackageHeader", 82 | ["package_size", "header_size", "version", "operation", "sequence_id"], 83 | ) 84 | 85 | HeaderStruct = struct.Struct(">I2H2I") 86 | 87 | 88 | def counter(start=1): 89 | while True: 90 | yield start 91 | start += 1 92 | 93 | 94 | 95 | 96 | class BLiveMsgPackage: 97 | """bilibili websocket message package""" 98 | 99 | def __init__(self) -> None: 100 | self.sequence = counter(0) 101 | 102 | def pack(self, data, operation, version=ProtocolVersion.NORMAL): 103 | body = json.dumps(data).encode("utf-8") 104 | header = HeaderStruct.pack( 105 | *PackageHeader( 106 | package_size=HeaderStruct.size + len(body), 107 | header_size=HeaderStruct.size, 108 | version=version, 109 | operation=operation, 110 | sequence_id=next(self.sequence), 111 | ) 112 | ) 113 | return header + body 114 | 115 | def zipped_notify_pkg_process( 116 | self, packages: list, data 117 | ): # 解压后的包处理代码 ,抽取为公共函数, data: 解压后的原始数据 118 | header = PackageHeader(*HeaderStruct.unpack(data[:16])) # 读取包头 119 | if len(data) > header.package_size: # 如果数据大小大于包头声明的大小,说明是粘包 120 | while True: 121 | # 先把第一个包放进去 / 放入包 122 | packages.append( 123 | (header, data[16 : header.package_size].decode("utf-8")) 124 | ) 125 | # 移动到下一个包 126 | data = data[header.package_size :] 127 | # 读取下一个包的包头 128 | header = PackageHeader(*HeaderStruct.unpack(data[:16])) 129 | if len(data) > header.package_size: 130 | # 如果数据还大于声明的package_size,说明还有1个以上的包 131 | continue 132 | else: 133 | # 剩下的数据刚好就是一个包,直接放,然后退出循环 134 | packages.append((header, data[16:].decode("utf-8"))) # 直接放第二个包 135 | break 136 | else: 137 | # 如果数据大小不大于包头声明的大小,说明是单个包太大压缩的。直接放入 138 | packages.append((header, data[16:].decode("utf-8"))) 139 | 140 | def unpack(self, data) -> list: 141 | packages = [] # 装处理好的数据包用 142 | header = PackageHeader(*HeaderStruct.unpack(data[:16])) # 读取数据包的头部 143 | data = data[16:] # 读取数据包的数据段 144 | 145 | # 心跳包处理 146 | if header.operation == Operation.HEARTBEAT_REPLY: 147 | popularity = struct.unpack("!I", data[:4])[0] 148 | payload = data[4:].decode("utf-8") 149 | plain_text = "{"+"\"cmd\":\"HEARTBEAT_REPLY\",\"popularity\":{},\"payload\":{}".format(popularity,payload)+"}" 150 | packages.append((header, plain_text)) 151 | 152 | # 通知包处理 153 | elif header.operation == Operation.NOTIFY: 154 | 155 | # NOTIFY 消息可能会粘包 156 | if header.version == ProtocolVersion.DEFLATE: 157 | # 先zlib解码,拆包 158 | data = zlib.decompress(data) 159 | self.zipped_notify_pkg_process(packages, data) 160 | 161 | elif header.version == ProtocolVersion.BROTLI: 162 | # 与 zlib 逻辑相同,先解码,然后数据可能要拆包 163 | data = brotli.decompress(data) 164 | self.zipped_notify_pkg_process(packages, data) 165 | 166 | elif header.version == ProtocolVersion.NORMAL: 167 | # normal 直接decode 168 | packages.append((header, data.decode("utf-8"))) 169 | else: 170 | # TODO 抛出错误或者打印日志 171 | pass 172 | 173 | elif header.operation == Operation.AUTH_REPLY: 174 | packages.append((header, data.decode("utf-8"))) 175 | 176 | return packages 177 | 178 | 179 | packman = BLiveMsgPackage() 180 | 181 | 182 | class Events(str, enum.Enum): 183 | HEARTBEAT_REPLY="HEARTBEAT_REPLY" # 心跳包回复,带有当前主播的人气值 184 | LIVE = "LIVE" # 主播开播 185 | PREPARING = "PREPARING" # 下播【结束语】 186 | ROOM_CHANGE = "ROOM_CHANGE" # 房间信息改变 187 | ROOM_RANK = "ROOM_RANK" # 排名改变 188 | DANMU_MSG = "DANMU_MSG" # 接收到弹幕【自动回复】 189 | SEND_GIFT = "SEND_GIFT" # 有人送礼【答谢送礼】 190 | WELCOME_GUARD = "WELCOME_GUARD" # 舰长进入(不会触发) 191 | ENTRY_EFFECT = "ENTRY_EFFECT" # 舰长、高能榜、老爷进入【欢迎舰长】 192 | WELCOME = "WELCOME" # 老爷进入 193 | INTERACT_WORD = "INTERACT_WORD" # 用户进入【欢迎】 194 | ATTENTION = "ATTENTION" # 用户关注【答谢关注】 195 | SHARE = "SHARE" # 用户分享直播间 196 | SPECIAL_ATTENTION = "SPECIAL_ATTENTION" # 特别关注直播间,可用%special%判断 197 | ROOM_REAL_TIME_MESSAGE_UPDATE = "ROOM_REAL_TIME_MESSAGE_UPDATE" # 粉丝数量改变 198 | SUPER_CHAT_MESSAGE = "SUPER_CHAT_MESSAGE" # 醒目留言 199 | SUPER_CHAT_MESSAGE_JPN = "SUPER_CHAT_MESSAGE_JPN" # 醒目留言日文翻译 200 | SUPER_CHAT_MESSAGE_DELETE = "SUPER_CHAT_MESSAGE_DELETE" # 删除醒目留言 201 | ROOM_BLOCK_MSG = "ROOM_BLOCK_MSG" # 用户被禁言,%uname%昵称 202 | GUARD_BUY = "GUARD_BUY" # 有人上船 203 | FIRST_GUARD = "FIRST_GUARD" # 用户初次上船 204 | NEW_GUARD_COUNT = ( 205 | "NEW_GUARD_COUNT" # 船员数量改变事件,%uname%新船员昵称,%num%获取大航海数量,附带直播间信息json数据 206 | ) 207 | USER_TOAST_MSG = "USER_TOAST_MSG" # 上船附带的通知 208 | HOT_RANK_CHANGED = "HOT_RANK_CHANGED" # 热门榜排名改变 209 | HOT_RANK_SETTLEMENT = "HOT_RANK_SETTLEMENT" # 荣登热门榜topX 210 | HOT_RANK = "HOT_RANK" # 热门榜xx榜topX,%text%获取排名 211 | ONLINE_RANK_V2 = "ONLINE_RANK_V2" # 礼物榜(高能榜)刷新 212 | ONLINE_RANK_TOP3 = "ONLINE_RANK_TOP3" # 高能榜TOP3改变 213 | ONLINE_RANK_COUNT = "ONLINE_RANK_COUNT" # 高能榜改变 214 | NOTICE_MSG = "NOTICE_MSG" # 上船等带的通知 215 | COMBO_SEND = "COMBO_SEND" # 礼物连击 216 | SPECIAL_GIFT = "SPECIAL_GIFT" # 定制的专属礼物 217 | ANCHOR_LOT_CHECKSTATUS = "ANCHOR_LOT_CHECKSTATUS" # 天选时刻前的审核 218 | ANCHOR_LOT_START = "ANCHOR_LOT_START" # 开启天选 219 | ANCHOR_LOT_END = "ANCHOR_LOT_END" # 天选结束 220 | ANCHOR_LOT_AWARD = "ANCHOR_LOT_AWARD" # 天选结果推送 221 | VOICE_JOIN_ROOM_COUNT_INFO = "VOICE_JOIN_ROOM_COUNT_INFO" # 申请连麦队列变化 222 | VOICE_JOIN_LIST = "VOICE_JOIN_LIST" # 连麦申请、取消连麦申请 223 | VOICE_JOIN_STATUS = "VOICE_JOIN_STATUS" # 开始连麦、结束连麦 224 | WARNING = "WARNING" # 被警告,%text%可获取内容 225 | CUT_OFF = "CUT_OFF" # 被超管切断 226 | room_admin_entrance = "room_admin_entrance" # 设置房管 227 | ROOM_ADMINS = "ROOM_ADMINS" # 房管数量改变 228 | MEDAL_UPGRADE = "MEDAL_UPGRADE" # 勋章升级,仅送礼物后触发,需设置中开启“监听勋章升级”。%medal_level%获取新等级(但用户当前勋章不一定是本直播间) 229 | STOP_LIVE_ROOM_LIST = "STOP_LIVE_ROOM_LIST" # 停止直播的房间(这些房间会关闭ws连接) 230 | WIDGET_BANNER = "WIDGET_BANNER" # 小部件横幅 231 | PK_BATTLE_PROCESS_NEW = "PK_BATTLE_PROCESS_NEW" # 开始pk 232 | PK_BATTLE_PROCESS = "PK_BATTLE_PROCESS" # pk 233 | COMMON_NOTICE_DANMAKU = "COMMON_NOTICE_DANMAKU" # 弹幕通知 234 | HOT_RANK_CHANGED_V2 = "HOT_RANK_CHANGED_V2" # 热门榜改变v2 235 | PK_BATTLE_SETTLE = "PK_BATTLE_SETTLE" # pk结果 236 | PK_BATTLE_PRE_NEW = "PK_BATTLE_PRE_NEW" # pk预创建 237 | LIVE_INTERACTIVE_GAME = "LIVE_INTERACTIVE_GAME" # 在线互动游戏 送礼物参与 238 | -------------------------------------------------------------------------------- /blive/eeframework.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | import json 3 | import asyncio 4 | from typing import List, Union 5 | import aiohttp 6 | from apscheduler.schedulers.asyncio import AsyncIOScheduler 7 | from pyee import AsyncIOEventEmitter 8 | from .core import ( 9 | BLiveMsgPackage, 10 | PackageHeader, 11 | Events, 12 | Operation, 13 | get_blive_room_info, 14 | get_blive_ws_url, 15 | certification, 16 | heartbeat, 17 | ) 18 | 19 | 20 | class BLiverCtx: 21 | def __init__(self, bliver, msg) -> None: 22 | self.ws = bliver.ws 23 | self.bliver: BLiver = bliver 24 | self.msg: tuple[PackageHeader, dict] = msg # 原始消息 25 | self.header: PackageHeader = self.msg[0] # 消息头部 26 | self.body: dict = json.loads(msg[1]) 27 | 28 | 29 | class BLiver(AsyncIOEventEmitter): 30 | real_room_id: Union[None, int] 31 | uname: Union[None, str] 32 | 33 | def __init__(self, room_id, uid=0): 34 | super().__init__() 35 | self.running = False 36 | 37 | self.room_id = room_id 38 | self.uid = uid 39 | self.aio_session = aiohttp.ClientSession() 40 | self.packman = BLiveMsgPackage() 41 | self.scheduler = AsyncIOScheduler(timezone="Asia/ShangHai") 42 | 43 | def register_handler(self, event: Union[Events, List[Events]], handler): 44 | warnings.warn( 45 | "`register_handler` is deprecated function please use `on`", 46 | DeprecationWarning, 47 | ) 48 | self.on(event, handler) 49 | 50 | async def heartbeat(self): 51 | try: 52 | if self.ws is not None and not self.ws.closed: 53 | await self.ws.send_bytes( 54 | self.packman.pack(heartbeat(), Operation.HEARTBEAT) 55 | ) 56 | return 57 | except ( 58 | aiohttp.ClientConnectionError, 59 | asyncio.TimeoutError, 60 | ConnectionError, 61 | ConnectionResetError, 62 | ): 63 | await self.connect() # 重新连接 64 | 65 | async def connect(self, retries=5): 66 | for i in range(retries): 67 | try: 68 | if not hasattr(self,"real_room_id") or not hasattr(self,"uname"): 69 | self.real_room_id, self.uname = await get_blive_room_info( 70 | self.room_id, self.aio_session 71 | ) 72 | url, token = await get_blive_ws_url(self.real_room_id, self.aio_session) 73 | self.ws = await self.aio_session.ws_connect(url) 74 | # 发送认证 75 | await self.ws.send_bytes( 76 | self.packman.pack( 77 | certification(self.real_room_id, token, uid=self.uid), 78 | Operation.AUTH, 79 | ) 80 | ) 81 | return 82 | except ( 83 | aiohttp.ClientConnectionError, 84 | asyncio.TimeoutError, 85 | ConnectionError, 86 | ConnectionResetError, 87 | ): 88 | await asyncio.sleep(1) 89 | # raise aiohttp.ClientConnectionError("与服务器连接失败") 90 | 91 | async def listen(self): 92 | self.running = True 93 | # start listening 94 | await self.connect() 95 | 96 | # 开始30s发送心跳包的定时任务 97 | self.scheduler.add_job(self.heartbeat, trigger="interval", seconds=30) 98 | self.scheduler.start() 99 | 100 | # 开始监听 101 | while self.running: 102 | try: 103 | msg = await self.ws.receive(timeout=60) 104 | if msg.type in ( 105 | aiohttp.WSMsgType.CLOSING, 106 | aiohttp.WSMsgType.CLOSED, 107 | aiohttp.WSMsgType.ERROR, 108 | ): 109 | if self.running: 110 | await self.connect() # reconnect 111 | continue 112 | else: 113 | return 0 114 | if msg.type != aiohttp.WSMsgType.BINARY: 115 | continue 116 | mq = self.packman.unpack(msg.data) 117 | ctxs = filter(lambda ctx: ctx.body.get("cmd", None), [BLiverCtx(self, m) for m in mq]) 118 | for ctx in ctxs: 119 | self.emit(ctx.body["cmd"], ctx) 120 | except ( 121 | aiohttp.ClientConnectionError, 122 | ConnectionResetError, 123 | asyncio.TimeoutError, 124 | ): 125 | await self.connect() 126 | 127 | async def graceful_close(self): 128 | self.running = False 129 | self.scheduler.shutdown() 130 | await self.aio_session.close() 131 | await self.ws.close() 132 | 133 | def run(self): 134 | loop = asyncio.get_event_loop() 135 | loop.create_task(self.listen()) 136 | loop.run_forever() 137 | 138 | def run_as_task(self): 139 | loop = asyncio.get_event_loop() 140 | return loop.create_task(self.listen()) -------------------------------------------------------------------------------- /blive/framework.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | import asyncio 4 | from typing import Awaitable, Dict, List, Union 5 | import loguru 6 | import aiohttp 7 | from aiohttp.client_ws import ClientWebSocketResponse 8 | from aiohttp.http_websocket import WSMessage 9 | from apscheduler.schedulers.asyncio import AsyncIOScheduler 10 | from apscheduler.util import _Undefined 11 | from requests.exceptions import ConnectionError 12 | 13 | from .core import ( 14 | BWS_MsgPackage, 15 | PackageHeader, 16 | Events, 17 | Operation, 18 | get_blive_room_info, 19 | get_blive_ws_url, 20 | certification, 21 | heartbeat, 22 | ) 23 | 24 | 25 | undefined = _Undefined() 26 | 27 | 28 | class ExitedException(Exception): 29 | pass 30 | 31 | 32 | class BLiverCtx(object): 33 | def __init__(self, bliver, msg) -> None: 34 | super().__init__() 35 | self.ws: ClientWebSocketResponse = bliver.ws 36 | self.msg = msg # 原始消息 37 | self.header: PackageHeader = msg[0] # 消息头部 38 | self.bliver: BLiver = bliver 39 | self.body = json.loads(msg[1]) 40 | 41 | 42 | class Channel: 43 | """ 44 | 消息类型,不直接用list代替的原因是方便后面加入middleware类 45 | """ 46 | 47 | def __init__(self) -> None: 48 | self.listeners = [] 49 | 50 | def register_handler(self, handler): 51 | self.listeners.append(handler) 52 | 53 | def __getitem__(self, idx): 54 | return self.listeners.__getitem__(idx) 55 | 56 | def __iter__(self): 57 | return iter(self.listeners) 58 | 59 | 60 | class Processor: 61 | def __init__(self, logger=None) -> None: 62 | self.logger = logger or loguru.logger 63 | self.channels: Dict[str, Channel] = {} 64 | 65 | def register(self, channel: str, handler: Awaitable): 66 | c = self.channels.get(channel, Channel()) 67 | c.register_handler(handler) 68 | self.channels[channel] = c 69 | 70 | async def process(self, ctx): 71 | if ctx.header.operation == Operation.NOTIFY: 72 | listeners = self.channels.get(ctx.body["cmd"], []) # 根据cmd 得到相应的处理句柄 73 | return await asyncio.gather(*[f(ctx) for f in listeners]) 74 | 75 | 76 | class BLiver: 77 | _global_catches = {} 78 | 79 | def catch(self, err_type): 80 | def _err_handler_wrapper(fn): 81 | self.register_error_handler(err_type, fn) 82 | 83 | return _err_handler_wrapper 84 | 85 | @classmethod 86 | def register_global_error_handler(cls, err_type, fn): 87 | err_handlers = cls._global_catches.get(err_type, []) 88 | err_handlers.append(fn) 89 | cls._global_catches[err_type] = err_handlers 90 | 91 | def register_error_handler(self, err_type, fn): 92 | err_handlers = self._catches.get(err_type, []) 93 | err_handlers.append(fn) 94 | self._catches[err_type] = err_handlers 95 | 96 | def __init__(self, roomid, uid=0, logger=None, log_level="INFO"): 97 | self.roomid = roomid 98 | self.uid = uid 99 | self.real_roomid, self.uname = get_blive_room_info(roomid) 100 | if not logger: 101 | self.logger = loguru.logger 102 | self.logger.remove() 103 | self.logger.add(sys.stderr, level=log_level) 104 | else: 105 | self.logger = logger 106 | self._catches = {} # to handle errors 107 | self._ws: ClientWebSocketResponse = None 108 | self.packman = BWS_MsgPackage() 109 | self.scheduler = AsyncIOScheduler(timezone="Asia/ShangHai") 110 | self.processor = Processor(logger=self.logger) 111 | self.aio_session = aiohttp.ClientSession() 112 | 113 | def on(self, event: Union[Events, List[Events]]): 114 | def f_wrapper(func): 115 | self.logger.debug("handler added,{}", func) 116 | if isinstance(event, list): 117 | for e in event: 118 | self.processor.register(e, func) 119 | else: 120 | self.processor.register(event, func) 121 | return func 122 | 123 | return f_wrapper 124 | 125 | def register_handler(self, event: Union[Events, List[Events]], handler): 126 | self.processor.register(event, handler) 127 | 128 | def scheduled( 129 | self, 130 | trigger, 131 | args=None, 132 | kwargs=None, 133 | id=None, 134 | name=None, 135 | misfire_grace_time=undefined, 136 | coalesce=undefined, 137 | max_instances=undefined, 138 | next_run_time=undefined, 139 | jobstore="default", 140 | executor="default", 141 | **trigger_args, 142 | ): 143 | def s_func_wrapper(func): 144 | self.logger.debug("scheduler job added,{}", func) 145 | self.scheduler.add_job( 146 | func, 147 | trigger=trigger, 148 | args=args, 149 | kwargs=kwargs, 150 | id=id, 151 | name=name, 152 | misfire_grace_time=misfire_grace_time, 153 | coalesce=coalesce, 154 | max_instances=max_instances, 155 | next_run_time=next_run_time, 156 | jobstore=jobstore, 157 | executor=executor, 158 | replace_existing=True, 159 | **trigger_args, 160 | ) 161 | return func 162 | 163 | return s_func_wrapper 164 | 165 | @property 166 | def ws(self): 167 | assert self._ws is not None 168 | return self._ws 169 | 170 | async def heartbeat(self): 171 | try: 172 | if self._ws is not None and not self._ws.closed: 173 | await self._ws.send_bytes( 174 | self.packman.pack(heartbeat(), Operation.HEARTBEAT) 175 | ) 176 | self.logger.debug("heartbeat sended") 177 | return 178 | else: 179 | self.logger.warning( 180 | "heartbeat msg not send successfully, because ws had closed" 181 | ) 182 | except ( 183 | aiohttp.ClientConnectionError, 184 | asyncio.TimeoutError, 185 | ConnectionError, 186 | ConnectionResetError, 187 | ): 188 | self.logger.warning("send heartbeat error, will reconnect ws") 189 | await self.connect() # 重新连接 190 | 191 | async def connect(self, retries=5): 192 | for i in range(retries): 193 | try: 194 | url, token = get_blive_ws_url(self.real_roomid) 195 | ws = await self.aio_session.ws_connect(url) 196 | self._ws = ws 197 | # 发送认证 198 | await ws.send_bytes( 199 | self.packman.pack( 200 | certification(self.real_roomid, token, uid=self.uid), 201 | Operation.AUTH, 202 | ) 203 | ) 204 | return 205 | except ( 206 | aiohttp.ClientConnectionError, 207 | asyncio.TimeoutError, 208 | ConnectionError, 209 | ConnectionResetError, 210 | ): 211 | self.logger.warning( 212 | "connect failed, will retry {}, current: {}", retries, i + 1 213 | ) 214 | await asyncio.sleep(1) 215 | self.logger.warning("reconnect fail") 216 | 217 | async def listen(self): 218 | # start listening 219 | await self.connect() 220 | 221 | # 开始30s发送心跳包的定时任务 222 | self.scheduler.add_job(self.heartbeat, trigger="interval", seconds=30) 223 | self.scheduler.start() 224 | 225 | # 开始监听 226 | while True: 227 | try: 228 | msg: WSMessage = await self.ws.receive(timeout=60) 229 | if msg.type in ( 230 | aiohttp.WSMsgType.CLOSING, 231 | aiohttp.WSMsgType.CLOSED, 232 | aiohttp.WSMsgType.ERROR, 233 | ): 234 | self.logger.warning("ws closed") 235 | await self.connect() # reconnect 236 | continue 237 | if msg.type != aiohttp.WSMsgType.BINARY: 238 | continue 239 | mq = self.packman.unpack(msg.data) 240 | self.logger.debug("received msg:\n{}", mq) 241 | tasks = [self.processor.process(BLiverCtx(self, m)) for m in mq] 242 | await asyncio.gather(*tasks) 243 | except ( 244 | aiohttp.ClientConnectionError, 245 | ConnectionResetError, 246 | asyncio.TimeoutError, 247 | ): 248 | self.logger.warning("ws conn will reconnect") 249 | await self.connect() 250 | 251 | # to handler errors 252 | except tuple(self._catches.keys()) as e: 253 | [eh(e,self) for eh in self._catches.get(type(e), [])] 254 | except tuple(BLiver._global_catches.keys()) as e: 255 | [eh(e,self) for eh in BLiver._global_catches.get(type(e), [])] 256 | 257 | async def graceful_close(self): 258 | await self._ws.close() 259 | await self.aio_session.close() 260 | self.scheduler.shutdown() 261 | self.running = False 262 | 263 | def run(self): 264 | loop = asyncio.get_event_loop() 265 | loop.create_task(self.listen()) 266 | loop.run_forever() 267 | 268 | def run_as_task(self): 269 | loop = asyncio.get_event_loop() 270 | return loop.create_task(self.listen()) 271 | -------------------------------------------------------------------------------- /blive/msg.py: -------------------------------------------------------------------------------- 1 | from abc import ABC 2 | import json 3 | from typing import List 4 | 5 | """ 6 | 消息操作封装类,目前只封装了弹幕消息操作 7 | """ 8 | 9 | 10 | def dict_chain_get(dic, chain, default=None): 11 | if isinstance(chain, str): 12 | chain = tuple(chain.split(".")) 13 | 14 | try: 15 | for k in chain: 16 | dic = dic[k] 17 | return dic 18 | except (TypeError, KeyError): 19 | return default 20 | 21 | 22 | class DictObject: 23 | def __getitem__(self, idx): 24 | return getattr(self, idx) 25 | 26 | def __setitem__(self, k, v): 27 | setattr(self, k, v) 28 | 29 | def __delitem__(self, k): 30 | delattr(self, k) 31 | 32 | 33 | class Medal(DictObject): 34 | def __init__(self, medal_name, medal_level) -> None: 35 | super(DictObject, self).__init__() 36 | self.medal_name = medal_name 37 | self.medal_level = medal_level 38 | 39 | 40 | class Sender(DictObject): 41 | def __init__(self, id, name, medal_name, medal_level) -> None: 42 | super(DictObject, self).__init__() 43 | self.id = id 44 | self.name = name 45 | self.medal = Medal(medal_name, medal_level) 46 | 47 | 48 | class BaseMsg(ABC): 49 | def __init__(self, body) -> None: 50 | super().__init__() 51 | self.body = body 52 | 53 | @property 54 | def cmd(self): 55 | return self.body["cmd"] 56 | 57 | def __repr__(self) -> str: 58 | return json.dumps(self.body) 59 | 60 | def chain_get(self, key_chain, default=None): 61 | return dict_chain_get(self.body, key_chain, default=default) 62 | 63 | 64 | class DanMuMsg(BaseMsg): 65 | def __init__(self, body) -> None: 66 | super(DanMuMsg, self).__init__(body) 67 | 68 | @property 69 | def content(self): 70 | return self.body["info"][1] 71 | 72 | @property 73 | def sender(self): 74 | return Sender( 75 | id=self.body["info"][2][0], 76 | name=self.body["info"][2][1], 77 | medal_name=self.body["info"][3][1] if self.body["info"][3] else "", 78 | medal_level=self.body["info"][3][0] if self.body["info"][3] else 0, 79 | ) 80 | 81 | @property 82 | def timestamp(self): 83 | return self.body["info"][9] 84 | 85 | 86 | class InteractWordMsg(BaseMsg): 87 | def __init__(self, body) -> None: 88 | super().__init__(body) 89 | 90 | @property 91 | def user(self): 92 | return Sender( 93 | id=dict_chain_get(self.body, "data.uid"), 94 | name=dict_chain_get(self.body, "data.uname"), 95 | medal_name=dict_chain_get(self.body, "data.fans_medal.medal_name"), 96 | medal_level=dict_chain_get(self.body, "data.fans_medal.medal_level"), 97 | ) 98 | 99 | @property 100 | def timestamp(self): 101 | return dict_chain_get(self.body, "data.timestamp") 102 | 103 | 104 | class StopLiveRoomListMsg(BaseMsg): 105 | def __init__(self, body) -> None: 106 | super().__init__(body) 107 | 108 | @property 109 | def room_id_list(self) -> List[int]: 110 | return dict_chain_get(self.body, "data.room_id_list") 111 | 112 | 113 | class HotRankChangeV2Msg(BaseMsg): 114 | def __init__(self, body) -> None: 115 | super().__init__(body) 116 | 117 | @property 118 | def area_name(self): 119 | return dict_chain_get(self.body, "data.area_name") 120 | 121 | @property 122 | def rank_desc(self): 123 | return dict_chain_get(self.body, "data.rank_desc") 124 | 125 | @property 126 | def rank(self): 127 | return dict_chain_get(self.body, "data.rank") 128 | 129 | @property 130 | def trend(self): 131 | return dict_chain_get(self.body, "data.trend") 132 | 133 | @property 134 | def timestamp(self): 135 | return dict_chain_get(self.body, "data.timestamp") 136 | 137 | 138 | class SendGiftMsg(BaseMsg): 139 | # TODO 礼物逻辑复杂, 考虑更复杂的封装类 140 | def __init__(self, body) -> None: 141 | super().__init__(body) 142 | 143 | @property 144 | def sender(self): 145 | return Sender( 146 | id=dict_chain_get(self.body, "data.uid"), 147 | name=dict_chain_get(self.body, "data.uname"), 148 | medal_name=dict_chain_get(self.body, "data.medal_info.medal_name"), 149 | medal_level=dict_chain_get(self.body, "data.medal_info.medal_level"), 150 | ) 151 | 152 | @property 153 | def action(self): 154 | return dict_chain_get(self.body, "data.action") 155 | 156 | @property 157 | def gift(self): 158 | return { 159 | "gift_id": dict_chain_get(self.body, "data.giftId"), 160 | "gift_name": dict_chain_get(self.body, "data.giftName"), 161 | "gift_type": dict_chain_get(self.body, "data.giftType"), 162 | } 163 | 164 | @property 165 | def combo(self): 166 | return { 167 | "batch_combo_id": dict_chain_get(self.body, "data.batch_combo_id"), 168 | "batch_combo_send": dict_chain_get(self.body, "data.batch_combo_send"), 169 | "combo_resources_id": dict_chain_get(self.body, "data.combo_resources_id"), 170 | "combo_send": dict_chain_get(self.body, "data.combo_send"), 171 | "combo_stay_time": dict_chain_get(self.body, "data.combo_stay_time"), 172 | "combo_total_coin": dict_chain_get(self.body, "data.combo_total_coin"), 173 | } 174 | 175 | 176 | class SuperChatMsg(BaseMsg): 177 | def __init__(self, body) -> None: 178 | super().__init__(body) 179 | 180 | @property 181 | def content(self): 182 | return dict_chain_get(self.body, "data.message") 183 | 184 | @property 185 | def sender(self): 186 | return Sender( 187 | id=dict_chain_get(self.body, "data.uid"), 188 | name=dict_chain_get(self.body, "data.user_info.uname"), 189 | medal_name=dict_chain_get(self.body, "data.medal_info.medal_name"), 190 | medal_level=dict_chain_get(self.body, "data.medal_info.medal_level"), 191 | ) 192 | 193 | @property 194 | def price(self): 195 | return dict_chain_get(self.body, "data.price") 196 | 197 | @property 198 | def start_time(self): 199 | return dict_chain_get(self.body, "data.start_time") 200 | 201 | @property 202 | def time(self): 203 | return dict_chain_get(self.body, "data.time") 204 | 205 | @property # 头像 206 | def avatar_url(self): 207 | return dict_chain_get(self.body, "data.user_info.face") 208 | 209 | @property 210 | def anchor_uname(self): 211 | return dict_chain_get(self.body, "data.medal_info.anchor_uname") 212 | 213 | @property # 背景色 214 | def color(self): 215 | return dict_chain_get(self.body, "data.background_bottom_color") 216 | 217 | 218 | 219 | class EntryEffectMsg(BaseMsg): 220 | def __init__(self, body) -> None: 221 | super().__init__(body) 222 | 223 | @property 224 | def uid(self): 225 | return dict_chain_get(self.body, "data.uid") 226 | 227 | @property 228 | def face(self): 229 | return dict_chain_get(self.body, "data.face") 230 | 231 | @property 232 | def copy_writting(self): 233 | return dict_chain_get(self.body, "data.copy_writing") 234 | 235 | @property 236 | def web_basemap_url(self): 237 | return dict_chain_get(self.body, "data.web_basemap_url") 238 | 239 | @property 240 | def basemap_url(self): 241 | return dict_chain_get(self.body, "data.basemap_url") 242 | 243 | 244 | class LiveInteractiveGameMsg(BaseMsg): 245 | def __init__(self, body) -> None: 246 | super().__init__(body) 247 | 248 | @property 249 | def uid(self): 250 | return dict_chain_get(self.body, "data.uid") 251 | 252 | @property 253 | def uname(self): 254 | return dict_chain_get(self.body, "data.uname") 255 | 256 | @property 257 | def uface(self): 258 | return dict_chain_get(self.body, "data.uface") 259 | 260 | @property 261 | def fans_medal_level(self): 262 | return dict_chain_get(self.body, "data.fans_medal_level") 263 | 264 | @property 265 | def guard_level(self): 266 | return dict_chain_get(self.body, "data.guard_level") 267 | 268 | @property 269 | def gift(self): 270 | return { 271 | "gift_id": dict_chain_get(self.body, "data.gift_id"), 272 | "gift_name": dict_chain_get(self.body, "data.gift_name"), 273 | "gift_num": dict_chain_get(self.body, "data.gift_num"), 274 | "price": dict_chain_get(self.body, "data.price"), 275 | "paid": dict_chain_get(self.body, "data.paid"), 276 | } 277 | 278 | def timestamp(self): 279 | return dict_chain_get(self.body, "data.timestamp") 280 | 281 | 282 | class OnlineRankCountMsg(BaseMsg): 283 | def __init__(self, body) -> None: 284 | super().__init__(body) 285 | 286 | @property 287 | def count(self): 288 | return dict_chain_get(self.body, "data.count") 289 | -------------------------------------------------------------------------------- /example/app.py: -------------------------------------------------------------------------------- 1 | from blive import BLiver, Events, BLiverCtx 2 | from blive.msg import ( 3 | DanMuMsg, 4 | EntryEffectMsg, 5 | HotRankChangeV2Msg, 6 | InteractWordMsg, 7 | OnlineRankCountMsg, 8 | SendGiftMsg, 9 | StopLiveRoomListMsg, 10 | SuperChatMsg, 11 | ) 12 | 13 | app = BLiver(510) 14 | 15 | 16 | @app.on(Events.DANMU_MSG) 17 | async def listen(ctx: BLiverCtx): 18 | danmu = DanMuMsg(ctx.body) 19 | print( 20 | f'[弹幕] {danmu.sender.name} ({danmu.sender.medal.medal_name}:{danmu.sender.medal.medal_level}): "{danmu.content}"\n' 21 | ) 22 | 23 | @app.on(Events.HEARTBEAT_REPLY) 24 | async def liver_popularity(ctx: BLiverCtx): 25 | print(ctx.body['popularity']) 26 | 27 | @app.on(Events.INTERACT_WORD) 28 | async def listen_join(ctx: BLiverCtx): 29 | join = InteractWordMsg(ctx.body) 30 | print( 31 | "[欢迎]", 32 | f"{join.user['name']} ({join.user['medal']['medal_name']}:{join.user['medal']['medal_level']})", 33 | "进入直播间\n", 34 | ) 35 | 36 | 37 | @app.on(Events.SUPER_CHAT_MESSAGE) 38 | async def listen_sc(ctx: BLiverCtx): 39 | msg = SuperChatMsg(ctx.body) 40 | print( 41 | f"[sc] 感谢 {msg.sender['name']}({msg.sender['medal']['medal_name']}:{msg.sender['medal']['medal_level']})的价值 {msg.price} 的sc\n\n\t{msg.content}\n" 42 | ) 43 | 44 | 45 | @app.on(Events.SEND_GIFT) 46 | async def listen_gift(ctx: BLiverCtx): 47 | msg = SendGiftMsg(ctx.body) 48 | print( 49 | f"[礼物] {msg.sender['name']} ({msg.sender['medal']['medal_name']}:{msg.sender['medal']['medal_level']}) 送出 {msg.gift['gift_name']}\n" 50 | ) 51 | 52 | 53 | @app.on(Events.HOT_RANK_CHANGED_V2) 54 | async def hot(ctx: BLiverCtx): 55 | msg = HotRankChangeV2Msg(ctx.body) 56 | print( 57 | f"[通知] 恭喜 {ctx.bliver.uname} 在 {msg.area_name} 区 的 {msg.rank_desc} 榜单中获得第 {msg.rank} 名\n" 58 | ) 59 | 60 | 61 | @app.on(Events.ENTRY_EFFECT) 62 | async def welcome_captain(ctx: BLiverCtx): 63 | msg = EntryEffectMsg(ctx.body) 64 | print(f"[热烈欢迎] {msg.copy_writting}\n") 65 | 66 | 67 | @app.on(Events.STOP_LIVE_ROOM_LIST) 68 | async def stop_live_room_list(ctx: BLiverCtx): 69 | # 监听停止直播的房间 70 | msg = StopLiveRoomListMsg(ctx.body) 71 | print(f"[通知] 停止直播的房间列表:{msg.room_id_list}\n") 72 | 73 | 74 | @app.on(Events.ONLINE_RANK_COUNT) 75 | async def online_rank(ctx): 76 | msg = OnlineRankCountMsg(ctx.body) 77 | print(f"[通知] 当前在线人气排名 {msg.count}\n") 78 | 79 | 80 | app.run() 81 | -------------------------------------------------------------------------------- /example/multi_room.py: -------------------------------------------------------------------------------- 1 | """监听多个直播间的例子""" 2 | 3 | import asyncio 4 | from blive import BLiver, Events, BLiverCtx 5 | from blive.msg import DanMuMsg,InteractWordMsg 6 | 7 | 8 | # 定义弹幕事件handler 9 | async def listen(ctx: BLiverCtx): 10 | danmu = DanMuMsg(ctx.body) 11 | print( 12 | f'\n【{ctx.bliver.uname}】{danmu.sender.name} ({danmu.sender.medal.medal_name}:{danmu.sender.medal.medal_level}): "{danmu.content}"\n' 13 | ) 14 | 15 | async def listen_join(ctx: BLiverCtx): 16 | join = InteractWordMsg(ctx.body) 17 | print( 18 | f"\n【{ctx.bliver.uname}】欢迎", 19 | f"{join.user['name']} ({join.user['medal']['medal_name']}:{join.user['medal']['medal_level']})", 20 | "进入直播间", 21 | ) 22 | 23 | async def main(): 24 | # 两个直播间 25 | hai7 = BLiver(7777) 26 | azi = BLiver(510) 27 | 28 | azi.on(Events.DANMU_MSG, listen) 29 | azi.on(Events.INTERACT_WORD, listen_join) 30 | # 注册handler 31 | hai7.on(Events.DANMU_MSG, listen) 32 | hai7.on(Events.INTERACT_WORD, listen_join) 33 | 34 | # 以异步task的形式运行 35 | task1 = hai7.run_as_task() 36 | task2 = azi.run_as_task() 37 | 38 | # await 两个任务 39 | await asyncio.gather(task1, task2) 40 | 41 | 42 | if __name__ == "__main__": 43 | asyncio.run(main()) 44 | -------------------------------------------------------------------------------- /example/with_fastapi.py: -------------------------------------------------------------------------------- 1 | import uvicorn 2 | from fastapi import FastAPI 3 | from blive import BLiver, Events 4 | from blive.msg import DanMuMsg 5 | 6 | app = FastAPI() 7 | 8 | BLIVER_POOL = {} 9 | 10 | 11 | def create_bliver(roomid): 12 | # 定义弹幕事件handler 13 | async def listen(ctx): 14 | danmu = DanMuMsg(ctx.body) 15 | print( 16 | f'\n{danmu.sender.name} ({danmu.sender.medal.medal_name}:{danmu.sender.medal.medal_level}): "{danmu.content}"\n' 17 | ) 18 | 19 | b = BLiver(roomid) 20 | b.on(Events.DANMU_MSG, listen) 21 | return b 22 | 23 | 24 | @app.get("/create") 25 | async def create_new_bliver(roomid: int): 26 | room = BLIVER_POOL.get(roomid, None) 27 | if not room: 28 | b = create_bliver(roomid) 29 | BLIVER_POOL[roomid] = b.run_as_task() 30 | return {"msg": "创建一个新直播间弹幕监听成功"} 31 | 32 | 33 | @app.get("/del") 34 | async def rm_bliver(roomid: int): 35 | room = BLIVER_POOL.get(roomid, None) 36 | if room: 37 | room.cancel() 38 | BLIVER_POOL.pop(roomid) 39 | return {"msg": "移除直播间弹幕监听成功"} 40 | 41 | 42 | @app.get("/show") 43 | async def show(): 44 | return list(BLIVER_POOL.keys()) 45 | 46 | 47 | if __name__ == "__main__": 48 | uvicorn.run(app) -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "aiodns" 5 | version = "3.0.0" 6 | description = "Simple DNS resolver for asyncio" 7 | category = "main" 8 | optional = false 9 | python-versions = "*" 10 | files = [ 11 | {file = "aiodns-3.0.0-py3-none-any.whl", hash = "sha256:2b19bc5f97e5c936638d28e665923c093d8af2bf3aa88d35c43417fa25d136a2"}, 12 | {file = "aiodns-3.0.0.tar.gz", hash = "sha256:946bdfabe743fceeeb093c8a010f5d1645f708a241be849e17edfb0e49e08cd6"}, 13 | ] 14 | 15 | [package.dependencies] 16 | pycares = ">=4.0.0" 17 | 18 | [[package]] 19 | name = "aiohttp" 20 | version = "3.8.3" 21 | description = "Async http client/server framework (asyncio)" 22 | category = "main" 23 | optional = false 24 | python-versions = ">=3.6" 25 | files = [ 26 | {file = "aiohttp-3.8.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ba71c9b4dcbb16212f334126cc3d8beb6af377f6703d9dc2d9fb3874fd667ee9"}, 27 | {file = "aiohttp-3.8.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d24b8bb40d5c61ef2d9b6a8f4528c2f17f1c5d2d31fed62ec860f6006142e83e"}, 28 | {file = "aiohttp-3.8.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f88df3a83cf9df566f171adba39d5bd52814ac0b94778d2448652fc77f9eb491"}, 29 | {file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97decbb3372d4b69e4d4c8117f44632551c692bb1361b356a02b97b69e18a62"}, 30 | {file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:309aa21c1d54b8ef0723181d430347d7452daaff93e8e2363db8e75c72c2fb2d"}, 31 | {file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad5383a67514e8e76906a06741febd9126fc7c7ff0f599d6fcce3e82b80d026f"}, 32 | {file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20acae4f268317bb975671e375493dbdbc67cddb5f6c71eebdb85b34444ac46b"}, 33 | {file = "aiohttp-3.8.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05a3c31c6d7cd08c149e50dc7aa2568317f5844acd745621983380597f027a18"}, 34 | {file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d6f76310355e9fae637c3162936e9504b4767d5c52ca268331e2756e54fd4ca5"}, 35 | {file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:256deb4b29fe5e47893fa32e1de2d73c3afe7407738bd3c63829874661d4822d"}, 36 | {file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5c59fcd80b9049b49acd29bd3598cada4afc8d8d69bd4160cd613246912535d7"}, 37 | {file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:059a91e88f2c00fe40aed9031b3606c3f311414f86a90d696dd982e7aec48142"}, 38 | {file = "aiohttp-3.8.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2feebbb6074cdbd1ac276dbd737b40e890a1361b3cc30b74ac2f5e24aab41f7b"}, 39 | {file = "aiohttp-3.8.3-cp310-cp310-win32.whl", hash = "sha256:5bf651afd22d5f0c4be16cf39d0482ea494f5c88f03e75e5fef3a85177fecdeb"}, 40 | {file = "aiohttp-3.8.3-cp310-cp310-win_amd64.whl", hash = "sha256:653acc3880459f82a65e27bd6526e47ddf19e643457d36a2250b85b41a564715"}, 41 | {file = "aiohttp-3.8.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:86fc24e58ecb32aee09f864cb11bb91bc4c1086615001647dbfc4dc8c32f4008"}, 42 | {file = "aiohttp-3.8.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75e14eac916f024305db517e00a9252714fce0abcb10ad327fb6dcdc0d060f1d"}, 43 | {file = "aiohttp-3.8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d1fde0f44029e02d02d3993ad55ce93ead9bb9b15c6b7ccd580f90bd7e3de476"}, 44 | {file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ab94426ddb1ecc6a0b601d832d5d9d421820989b8caa929114811369673235c"}, 45 | {file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89d2e02167fa95172c017732ed7725bc8523c598757f08d13c5acca308e1a061"}, 46 | {file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:02f9a2c72fc95d59b881cf38a4b2be9381b9527f9d328771e90f72ac76f31ad8"}, 47 | {file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c7149272fb5834fc186328e2c1fa01dda3e1fa940ce18fded6d412e8f2cf76d"}, 48 | {file = "aiohttp-3.8.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:512bd5ab136b8dc0ffe3fdf2dfb0c4b4f49c8577f6cae55dca862cd37a4564e2"}, 49 | {file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7018ecc5fe97027214556afbc7c502fbd718d0740e87eb1217b17efd05b3d276"}, 50 | {file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:88c70ed9da9963d5496d38320160e8eb7e5f1886f9290475a881db12f351ab5d"}, 51 | {file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:da22885266bbfb3f78218dc40205fed2671909fbd0720aedba39b4515c038091"}, 52 | {file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:e65bc19919c910127c06759a63747ebe14f386cda573d95bcc62b427ca1afc73"}, 53 | {file = "aiohttp-3.8.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:08c78317e950e0762c2983f4dd58dc5e6c9ff75c8a0efeae299d363d439c8e34"}, 54 | {file = "aiohttp-3.8.3-cp311-cp311-win32.whl", hash = "sha256:45d88b016c849d74ebc6f2b6e8bc17cabf26e7e40c0661ddd8fae4c00f015697"}, 55 | {file = "aiohttp-3.8.3-cp311-cp311-win_amd64.whl", hash = "sha256:96372fc29471646b9b106ee918c8eeb4cca423fcbf9a34daa1b93767a88a2290"}, 56 | {file = "aiohttp-3.8.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c971bf3786b5fad82ce5ad570dc6ee420f5b12527157929e830f51c55dc8af77"}, 57 | {file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff25f48fc8e623d95eca0670b8cc1469a83783c924a602e0fbd47363bb54aaca"}, 58 | {file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e381581b37db1db7597b62a2e6b8b57c3deec95d93b6d6407c5b61ddc98aca6d"}, 59 | {file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db19d60d846283ee275d0416e2a23493f4e6b6028825b51290ac05afc87a6f97"}, 60 | {file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25892c92bee6d9449ffac82c2fe257f3a6f297792cdb18ad784737d61e7a9a85"}, 61 | {file = "aiohttp-3.8.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:398701865e7a9565d49189f6c90868efaca21be65c725fc87fc305906be915da"}, 62 | {file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:4a4fbc769ea9b6bd97f4ad0b430a6807f92f0e5eb020f1e42ece59f3ecfc4585"}, 63 | {file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:b29bfd650ed8e148f9c515474a6ef0ba1090b7a8faeee26b74a8ff3b33617502"}, 64 | {file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:1e56b9cafcd6531bab5d9b2e890bb4937f4165109fe98e2b98ef0dcfcb06ee9d"}, 65 | {file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ec40170327d4a404b0d91855d41bfe1fe4b699222b2b93e3d833a27330a87a6d"}, 66 | {file = "aiohttp-3.8.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2df5f139233060578d8c2c975128fb231a89ca0a462b35d4b5fcf7c501ebdbe1"}, 67 | {file = "aiohttp-3.8.3-cp36-cp36m-win32.whl", hash = "sha256:f973157ffeab5459eefe7b97a804987876dd0a55570b8fa56b4e1954bf11329b"}, 68 | {file = "aiohttp-3.8.3-cp36-cp36m-win_amd64.whl", hash = "sha256:437399385f2abcd634865705bdc180c8314124b98299d54fe1d4c8990f2f9494"}, 69 | {file = "aiohttp-3.8.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:09e28f572b21642128ef31f4e8372adb6888846f32fecb288c8b0457597ba61a"}, 70 | {file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f3553510abdbec67c043ca85727396ceed1272eef029b050677046d3387be8d"}, 71 | {file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e168a7560b7c61342ae0412997b069753f27ac4862ec7867eff74f0fe4ea2ad9"}, 72 | {file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db4c979b0b3e0fa7e9e69ecd11b2b3174c6963cebadeecfb7ad24532ffcdd11a"}, 73 | {file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e164e0a98e92d06da343d17d4e9c4da4654f4a4588a20d6c73548a29f176abe2"}, 74 | {file = "aiohttp-3.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8a78079d9a39ca9ca99a8b0ac2fdc0c4d25fc80c8a8a82e5c8211509c523363"}, 75 | {file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:21b30885a63c3f4ff5b77a5d6caf008b037cb521a5f33eab445dc566f6d092cc"}, 76 | {file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4b0f30372cef3fdc262f33d06e7b411cd59058ce9174ef159ad938c4a34a89da"}, 77 | {file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:8135fa153a20d82ffb64f70a1b5c2738684afa197839b34cc3e3c72fa88d302c"}, 78 | {file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:ad61a9639792fd790523ba072c0555cd6be5a0baf03a49a5dd8cfcf20d56df48"}, 79 | {file = "aiohttp-3.8.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:978b046ca728073070e9abc074b6299ebf3501e8dee5e26efacb13cec2b2dea0"}, 80 | {file = "aiohttp-3.8.3-cp37-cp37m-win32.whl", hash = "sha256:0d2c6d8c6872df4a6ec37d2ede71eff62395b9e337b4e18efd2177de883a5033"}, 81 | {file = "aiohttp-3.8.3-cp37-cp37m-win_amd64.whl", hash = "sha256:21d69797eb951f155026651f7e9362877334508d39c2fc37bd04ff55b2007091"}, 82 | {file = "aiohttp-3.8.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ca9af5f8f5812d475c5259393f52d712f6d5f0d7fdad9acdb1107dd9e3cb7eb"}, 83 | {file = "aiohttp-3.8.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d90043c1882067f1bd26196d5d2db9aa6d268def3293ed5fb317e13c9413ea4"}, 84 | {file = "aiohttp-3.8.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d737fc67b9a970f3234754974531dc9afeea11c70791dcb7db53b0cf81b79784"}, 85 | {file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebf909ea0a3fc9596e40d55d8000702a85e27fd578ff41a5500f68f20fd32e6c"}, 86 | {file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5835f258ca9f7c455493a57ee707b76d2d9634d84d5d7f62e77be984ea80b849"}, 87 | {file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da37dcfbf4b7f45d80ee386a5f81122501ec75672f475da34784196690762f4b"}, 88 | {file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87f44875f2804bc0511a69ce44a9595d5944837a62caecc8490bbdb0e18b1342"}, 89 | {file = "aiohttp-3.8.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:527b3b87b24844ea7865284aabfab08eb0faf599b385b03c2aa91fc6edd6e4b6"}, 90 | {file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d5ba88df9aa5e2f806650fcbeedbe4f6e8736e92fc0e73b0400538fd25a4dd96"}, 91 | {file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e7b8813be97cab8cb52b1375f41f8e6804f6507fe4660152e8ca5c48f0436017"}, 92 | {file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:2dea10edfa1a54098703cb7acaa665c07b4e7568472a47f4e64e6319d3821ccf"}, 93 | {file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:713d22cd9643ba9025d33c4af43943c7a1eb8547729228de18d3e02e278472b6"}, 94 | {file = "aiohttp-3.8.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2d252771fc85e0cf8da0b823157962d70639e63cb9b578b1dec9868dd1f4f937"}, 95 | {file = "aiohttp-3.8.3-cp38-cp38-win32.whl", hash = "sha256:66bd5f950344fb2b3dbdd421aaa4e84f4411a1a13fca3aeb2bcbe667f80c9f76"}, 96 | {file = "aiohttp-3.8.3-cp38-cp38-win_amd64.whl", hash = "sha256:84b14f36e85295fe69c6b9789b51a0903b774046d5f7df538176516c3e422446"}, 97 | {file = "aiohttp-3.8.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16c121ba0b1ec2b44b73e3a8a171c4f999b33929cd2397124a8c7fcfc8cd9e06"}, 98 | {file = "aiohttp-3.8.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8d6aaa4e7155afaf994d7924eb290abbe81a6905b303d8cb61310a2aba1c68ba"}, 99 | {file = "aiohttp-3.8.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43046a319664a04b146f81b40e1545d4c8ac7b7dd04c47e40bf09f65f2437346"}, 100 | {file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:599418aaaf88a6d02a8c515e656f6faf3d10618d3dd95866eb4436520096c84b"}, 101 | {file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92a2964319d359f494f16011e23434f6f8ef0434acd3cf154a6b7bec511e2fb7"}, 102 | {file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73a4131962e6d91109bca6536416aa067cf6c4efb871975df734f8d2fd821b37"}, 103 | {file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598adde339d2cf7d67beaccda3f2ce7c57b3b412702f29c946708f69cf8222aa"}, 104 | {file = "aiohttp-3.8.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75880ed07be39beff1881d81e4a907cafb802f306efd6d2d15f2b3c69935f6fb"}, 105 | {file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0239da9fbafd9ff82fd67c16704a7d1bccf0d107a300e790587ad05547681c8"}, 106 | {file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4e3a23ec214e95c9fe85a58470b660efe6534b83e6cbe38b3ed52b053d7cb6ad"}, 107 | {file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:47841407cc89a4b80b0c52276f3cc8138bbbfba4b179ee3acbd7d77ae33f7ac4"}, 108 | {file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:54d107c89a3ebcd13228278d68f1436d3f33f2dd2af5415e3feaeb1156e1a62c"}, 109 | {file = "aiohttp-3.8.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c37c5cce780349d4d51739ae682dec63573847a2a8dcb44381b174c3d9c8d403"}, 110 | {file = "aiohttp-3.8.3-cp39-cp39-win32.whl", hash = "sha256:f178d2aadf0166be4df834c4953da2d7eef24719e8aec9a65289483eeea9d618"}, 111 | {file = "aiohttp-3.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:88e5be56c231981428f4f506c68b6a46fa25c4123a2e86d156c58a8369d31ab7"}, 112 | {file = "aiohttp-3.8.3.tar.gz", hash = "sha256:3828fb41b7203176b82fe5d699e0d845435f2374750a44b480ea6b930f6be269"}, 113 | ] 114 | 115 | [package.dependencies] 116 | aiosignal = ">=1.1.2" 117 | async-timeout = ">=4.0.0a3,<5.0" 118 | attrs = ">=17.3.0" 119 | charset-normalizer = ">=2.0,<3.0" 120 | frozenlist = ">=1.1.1" 121 | multidict = ">=4.5,<7.0" 122 | yarl = ">=1.0,<2.0" 123 | 124 | [package.extras] 125 | speedups = ["Brotli", "aiodns", "cchardet"] 126 | 127 | [[package]] 128 | name = "aiosignal" 129 | version = "1.3.1" 130 | description = "aiosignal: a list of registered asynchronous callbacks" 131 | category = "main" 132 | optional = false 133 | python-versions = ">=3.7" 134 | files = [ 135 | {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, 136 | {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, 137 | ] 138 | 139 | [package.dependencies] 140 | frozenlist = ">=1.1.0" 141 | 142 | [[package]] 143 | name = "apscheduler" 144 | version = "3.9.1.post1" 145 | description = "In-process task scheduler with Cron-like capabilities" 146 | category = "main" 147 | optional = false 148 | python-versions = "!=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 149 | files = [ 150 | {file = "APScheduler-3.9.1.post1-py2.py3-none-any.whl", hash = "sha256:c8c618241dbb2785ed5a687504b14cb1851d6f7b5a4edf3a51e39cc6a069967a"}, 151 | {file = "APScheduler-3.9.1.post1.tar.gz", hash = "sha256:b2bea0309569da53a7261bfa0ce19c67ddbfe151bda776a6a907579fdbd3eb2a"}, 152 | ] 153 | 154 | [package.dependencies] 155 | pytz = "*" 156 | setuptools = ">=0.7" 157 | six = ">=1.4.0" 158 | tzlocal = ">=2.0,<3.0.0 || >=4.0.0" 159 | 160 | [package.extras] 161 | asyncio = ["trollius"] 162 | doc = ["sphinx", "sphinx-rtd-theme"] 163 | gevent = ["gevent"] 164 | mongodb = ["pymongo (>=3.0)"] 165 | redis = ["redis (>=3.0)"] 166 | rethinkdb = ["rethinkdb (>=2.4.0)"] 167 | sqlalchemy = ["sqlalchemy (>=0.8)"] 168 | testing = ["mock", "pytest", "pytest-asyncio", "pytest-asyncio (<0.6)", "pytest-cov", "pytest-tornado5"] 169 | tornado = ["tornado (>=4.3)"] 170 | twisted = ["twisted"] 171 | zookeeper = ["kazoo"] 172 | 173 | [[package]] 174 | name = "async-timeout" 175 | version = "4.0.2" 176 | description = "Timeout context manager for asyncio programs" 177 | category = "main" 178 | optional = false 179 | python-versions = ">=3.6" 180 | files = [ 181 | {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, 182 | {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, 183 | ] 184 | 185 | [[package]] 186 | name = "attrs" 187 | version = "22.2.0" 188 | description = "Classes Without Boilerplate" 189 | category = "main" 190 | optional = false 191 | python-versions = ">=3.6" 192 | files = [ 193 | {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, 194 | {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, 195 | ] 196 | 197 | [package.extras] 198 | cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] 199 | dev = ["attrs[docs,tests]"] 200 | docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] 201 | tests = ["attrs[tests-no-zope]", "zope.interface"] 202 | tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] 203 | 204 | [[package]] 205 | name = "brotli" 206 | version = "1.0.9" 207 | description = "Python bindings for the Brotli compression library" 208 | category = "main" 209 | optional = false 210 | python-versions = "*" 211 | files = [ 212 | {file = "Brotli-1.0.9-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:268fe94547ba25b58ebc724680609c8ee3e5a843202e9a381f6f9c5e8bdb5c70"}, 213 | {file = "Brotli-1.0.9-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:c2415d9d082152460f2bd4e382a1e85aed233abc92db5a3880da2257dc7daf7b"}, 214 | {file = "Brotli-1.0.9-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5913a1177fc36e30fcf6dc868ce23b0453952c78c04c266d3149b3d39e1410d6"}, 215 | {file = "Brotli-1.0.9-cp27-cp27m-win32.whl", hash = "sha256:afde17ae04d90fbe53afb628f7f2d4ca022797aa093e809de5c3cf276f61bbfa"}, 216 | {file = "Brotli-1.0.9-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7cb81373984cc0e4682f31bc3d6be9026006d96eecd07ea49aafb06897746452"}, 217 | {file = "Brotli-1.0.9-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:db844eb158a87ccab83e868a762ea8024ae27337fc7ddcbfcddd157f841fdfe7"}, 218 | {file = "Brotli-1.0.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9744a863b489c79a73aba014df554b0e7a0fc44ef3f8a0ef2a52919c7d155031"}, 219 | {file = "Brotli-1.0.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a72661af47119a80d82fa583b554095308d6a4c356b2a554fdc2799bc19f2a43"}, 220 | {file = "Brotli-1.0.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ee83d3e3a024a9618e5be64648d6d11c37047ac48adff25f12fa4226cf23d1c"}, 221 | {file = "Brotli-1.0.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:19598ecddd8a212aedb1ffa15763dd52a388518c4550e615aed88dc3753c0f0c"}, 222 | {file = "Brotli-1.0.9-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:44bb8ff420c1d19d91d79d8c3574b8954288bdff0273bf788954064d260d7ab0"}, 223 | {file = "Brotli-1.0.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e23281b9a08ec338469268f98f194658abfb13658ee98e2b7f85ee9dd06caa91"}, 224 | {file = "Brotli-1.0.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3496fc835370da351d37cada4cf744039616a6db7d13c430035e901443a34daa"}, 225 | {file = "Brotli-1.0.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b83bb06a0192cccf1eb8d0a28672a1b79c74c3a8a5f2619625aeb6f28b3a82bb"}, 226 | {file = "Brotli-1.0.9-cp310-cp310-win32.whl", hash = "sha256:26d168aac4aaec9a4394221240e8a5436b5634adc3cd1cdf637f6645cecbf181"}, 227 | {file = "Brotli-1.0.9-cp310-cp310-win_amd64.whl", hash = "sha256:622a231b08899c864eb87e85f81c75e7b9ce05b001e59bbfbf43d4a71f5f32b2"}, 228 | {file = "Brotli-1.0.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cc0283a406774f465fb45ec7efb66857c09ffefbe49ec20b7882eff6d3c86d3a"}, 229 | {file = "Brotli-1.0.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:11d3283d89af7033236fa4e73ec2cbe743d4f6a81d41bd234f24bf63dde979df"}, 230 | {file = "Brotli-1.0.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c1306004d49b84bd0c4f90457c6f57ad109f5cc6067a9664e12b7b79a9948ad"}, 231 | {file = "Brotli-1.0.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1375b5d17d6145c798661b67e4ae9d5496920d9265e2f00f1c2c0b5ae91fbde"}, 232 | {file = "Brotli-1.0.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cab1b5964b39607a66adbba01f1c12df2e55ac36c81ec6ed44f2fca44178bf1a"}, 233 | {file = "Brotli-1.0.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8ed6a5b3d23ecc00ea02e1ed8e0ff9a08f4fc87a1f58a2530e71c0f48adf882f"}, 234 | {file = "Brotli-1.0.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cb02ed34557afde2d2da68194d12f5719ee96cfb2eacc886352cb73e3808fc5d"}, 235 | {file = "Brotli-1.0.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b3523f51818e8f16599613edddb1ff924eeb4b53ab7e7197f85cbc321cdca32f"}, 236 | {file = "Brotli-1.0.9-cp311-cp311-win32.whl", hash = "sha256:ba72d37e2a924717990f4d7482e8ac88e2ef43fb95491eb6e0d124d77d2a150d"}, 237 | {file = "Brotli-1.0.9-cp311-cp311-win_amd64.whl", hash = "sha256:3ffaadcaeafe9d30a7e4e1e97ad727e4f5610b9fa2f7551998471e3736738679"}, 238 | {file = "Brotli-1.0.9-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:c83aa123d56f2e060644427a882a36b3c12db93727ad7a7b9efd7d7f3e9cc2c4"}, 239 | {file = "Brotli-1.0.9-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:6b2ae9f5f67f89aade1fab0f7fd8f2832501311c363a21579d02defa844d9296"}, 240 | {file = "Brotli-1.0.9-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:68715970f16b6e92c574c30747c95cf8cf62804569647386ff032195dc89a430"}, 241 | {file = "Brotli-1.0.9-cp35-cp35m-win32.whl", hash = "sha256:defed7ea5f218a9f2336301e6fd379f55c655bea65ba2476346340a0ce6f74a1"}, 242 | {file = "Brotli-1.0.9-cp35-cp35m-win_amd64.whl", hash = "sha256:88c63a1b55f352b02c6ffd24b15ead9fc0e8bf781dbe070213039324922a2eea"}, 243 | {file = "Brotli-1.0.9-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:503fa6af7da9f4b5780bb7e4cbe0c639b010f12be85d02c99452825dd0feef3f"}, 244 | {file = "Brotli-1.0.9-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:40d15c79f42e0a2c72892bf407979febd9cf91f36f495ffb333d1d04cebb34e4"}, 245 | {file = "Brotli-1.0.9-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:93130612b837103e15ac3f9cbacb4613f9e348b58b3aad53721d92e57f96d46a"}, 246 | {file = "Brotli-1.0.9-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87fdccbb6bb589095f413b1e05734ba492c962b4a45a13ff3408fa44ffe6479b"}, 247 | {file = "Brotli-1.0.9-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:6d847b14f7ea89f6ad3c9e3901d1bc4835f6b390a9c71df999b0162d9bb1e20f"}, 248 | {file = "Brotli-1.0.9-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:495ba7e49c2db22b046a53b469bbecea802efce200dffb69b93dd47397edc9b6"}, 249 | {file = "Brotli-1.0.9-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:4688c1e42968ba52e57d8670ad2306fe92e0169c6f3af0089be75bbac0c64a3b"}, 250 | {file = "Brotli-1.0.9-cp36-cp36m-win32.whl", hash = "sha256:61a7ee1f13ab913897dac7da44a73c6d44d48a4adff42a5701e3239791c96e14"}, 251 | {file = "Brotli-1.0.9-cp36-cp36m-win_amd64.whl", hash = "sha256:1c48472a6ba3b113452355b9af0a60da5c2ae60477f8feda8346f8fd48e3e87c"}, 252 | {file = "Brotli-1.0.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3b78a24b5fd13c03ee2b7b86290ed20efdc95da75a3557cc06811764d5ad1126"}, 253 | {file = "Brotli-1.0.9-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:9d12cf2851759b8de8ca5fde36a59c08210a97ffca0eb94c532ce7b17c6a3d1d"}, 254 | {file = "Brotli-1.0.9-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:6c772d6c0a79ac0f414a9f8947cc407e119b8598de7621f39cacadae3cf57d12"}, 255 | {file = "Brotli-1.0.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29d1d350178e5225397e28ea1b7aca3648fcbab546d20e7475805437bfb0a130"}, 256 | {file = "Brotli-1.0.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7bbff90b63328013e1e8cb50650ae0b9bac54ffb4be6104378490193cd60f85a"}, 257 | {file = "Brotli-1.0.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ec1947eabbaf8e0531e8e899fc1d9876c179fc518989461f5d24e2223395a9e3"}, 258 | {file = "Brotli-1.0.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12effe280b8ebfd389022aa65114e30407540ccb89b177d3fbc9a4f177c4bd5d"}, 259 | {file = "Brotli-1.0.9-cp37-cp37m-win32.whl", hash = "sha256:f909bbbc433048b499cb9db9e713b5d8d949e8c109a2a548502fb9aa8630f0b1"}, 260 | {file = "Brotli-1.0.9-cp37-cp37m-win_amd64.whl", hash = "sha256:97f715cf371b16ac88b8c19da00029804e20e25f30d80203417255d239f228b5"}, 261 | {file = "Brotli-1.0.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e16eb9541f3dd1a3e92b89005e37b1257b157b7256df0e36bd7b33b50be73bcb"}, 262 | {file = "Brotli-1.0.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:160c78292e98d21e73a4cc7f76a234390e516afcd982fa17e1422f7c6a9ce9c8"}, 263 | {file = "Brotli-1.0.9-cp38-cp38-manylinux1_i686.whl", hash = "sha256:b663f1e02de5d0573610756398e44c130add0eb9a3fc912a09665332942a2efb"}, 264 | {file = "Brotli-1.0.9-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5b6ef7d9f9c38292df3690fe3e302b5b530999fa90014853dcd0d6902fb59f26"}, 265 | {file = "Brotli-1.0.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a674ac10e0a87b683f4fa2b6fa41090edfd686a6524bd8dedbd6138b309175c"}, 266 | {file = "Brotli-1.0.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e2d9e1cbc1b25e22000328702b014227737756f4b5bf5c485ac1d8091ada078b"}, 267 | {file = "Brotli-1.0.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b336c5e9cf03c7be40c47b5fd694c43c9f1358a80ba384a21969e0b4e66a9b17"}, 268 | {file = "Brotli-1.0.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:85f7912459c67eaab2fb854ed2bc1cc25772b300545fe7ed2dc03954da638649"}, 269 | {file = "Brotli-1.0.9-cp38-cp38-win32.whl", hash = "sha256:35a3edbe18e876e596553c4007a087f8bcfd538f19bc116917b3c7522fca0429"}, 270 | {file = "Brotli-1.0.9-cp38-cp38-win_amd64.whl", hash = "sha256:269a5743a393c65db46a7bb982644c67ecba4b8d91b392403ad8a861ba6f495f"}, 271 | {file = "Brotli-1.0.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2aad0e0baa04517741c9bb5b07586c642302e5fb3e75319cb62087bd0995ab19"}, 272 | {file = "Brotli-1.0.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5cb1e18167792d7d21e21365d7650b72d5081ed476123ff7b8cac7f45189c0c7"}, 273 | {file = "Brotli-1.0.9-cp39-cp39-manylinux1_i686.whl", hash = "sha256:16d528a45c2e1909c2798f27f7bf0a3feec1dc9e50948e738b961618e38b6a7b"}, 274 | {file = "Brotli-1.0.9-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:56d027eace784738457437df7331965473f2c0da2c70e1a1f6fdbae5402e0389"}, 275 | {file = "Brotli-1.0.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bf919756d25e4114ace16a8ce91eb340eb57a08e2c6950c3cebcbe3dff2a5e7"}, 276 | {file = "Brotli-1.0.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e4c4e92c14a57c9bd4cb4be678c25369bf7a092d55fd0866f759e425b9660806"}, 277 | {file = "Brotli-1.0.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e48f4234f2469ed012a98f4b7874e7f7e173c167bed4934912a29e03167cf6b1"}, 278 | {file = "Brotli-1.0.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9ed4c92a0665002ff8ea852353aeb60d9141eb04109e88928026d3c8a9e5433c"}, 279 | {file = "Brotli-1.0.9-cp39-cp39-win32.whl", hash = "sha256:cfc391f4429ee0a9370aa93d812a52e1fee0f37a81861f4fdd1f4fb28e8547c3"}, 280 | {file = "Brotli-1.0.9-cp39-cp39-win_amd64.whl", hash = "sha256:854c33dad5ba0fbd6ab69185fec8dab89e13cda6b7d191ba111987df74f38761"}, 281 | {file = "Brotli-1.0.9-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9749a124280a0ada4187a6cfd1ffd35c350fb3af79c706589d98e088c5044267"}, 282 | {file = "Brotli-1.0.9-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:73fd30d4ce0ea48010564ccee1a26bfe39323fde05cb34b5863455629db61dc7"}, 283 | {file = "Brotli-1.0.9-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02177603aaca36e1fd21b091cb742bb3b305a569e2402f1ca38af471777fb019"}, 284 | {file = "Brotli-1.0.9-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:76ffebb907bec09ff511bb3acc077695e2c32bc2142819491579a695f77ffd4d"}, 285 | {file = "Brotli-1.0.9-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b43775532a5904bc938f9c15b77c613cb6ad6fb30990f3b0afaea82797a402d8"}, 286 | {file = "Brotli-1.0.9-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5bf37a08493232fbb0f8229f1824b366c2fc1d02d64e7e918af40acd15f3e337"}, 287 | {file = "Brotli-1.0.9-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:330e3f10cd01da535c70d09c4283ba2df5fb78e915bea0a28becad6e2ac010be"}, 288 | {file = "Brotli-1.0.9-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e1abbeef02962596548382e393f56e4c94acd286bd0c5afba756cffc33670e8a"}, 289 | {file = "Brotli-1.0.9-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3148362937217b7072cf80a2dcc007f09bb5ecb96dae4617316638194113d5be"}, 290 | {file = "Brotli-1.0.9-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:336b40348269f9b91268378de5ff44dc6fbaa2268194f85177b53463d313842a"}, 291 | {file = "Brotli-1.0.9-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b09a16a1950b9ef495a0f8b9d0a87599a9d1f179e2d4ac014b2ec831f87e7"}, 292 | {file = "Brotli-1.0.9-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c8e521a0ce7cf690ca84b8cc2272ddaf9d8a50294fd086da67e517439614c755"}, 293 | {file = "Brotli-1.0.9.zip", hash = "sha256:4d1b810aa0ed773f81dceda2cc7b403d01057458730e309856356d4ef4188438"}, 294 | ] 295 | 296 | [[package]] 297 | name = "cffi" 298 | version = "1.15.1" 299 | description = "Foreign Function Interface for Python calling C code." 300 | category = "main" 301 | optional = false 302 | python-versions = "*" 303 | files = [ 304 | {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, 305 | {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, 306 | {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, 307 | {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, 308 | {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, 309 | {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, 310 | {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, 311 | {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, 312 | {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, 313 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, 314 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, 315 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, 316 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, 317 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, 318 | {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, 319 | {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, 320 | {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, 321 | {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, 322 | {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, 323 | {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, 324 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, 325 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, 326 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, 327 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, 328 | {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, 329 | {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, 330 | {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, 331 | {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, 332 | {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, 333 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, 334 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, 335 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, 336 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, 337 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, 338 | {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, 339 | {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, 340 | {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, 341 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, 342 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, 343 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, 344 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, 345 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, 346 | {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, 347 | {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, 348 | {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, 349 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, 350 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, 351 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, 352 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, 353 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, 354 | {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, 355 | {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, 356 | {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, 357 | {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, 358 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, 359 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, 360 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, 361 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, 362 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, 363 | {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, 364 | {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, 365 | {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, 366 | {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, 367 | {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, 368 | ] 369 | 370 | [package.dependencies] 371 | pycparser = "*" 372 | 373 | [[package]] 374 | name = "charset-normalizer" 375 | version = "2.1.1" 376 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 377 | category = "main" 378 | optional = false 379 | python-versions = ">=3.6.0" 380 | files = [ 381 | {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, 382 | {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, 383 | ] 384 | 385 | [package.extras] 386 | unicode-backport = ["unicodedata2"] 387 | 388 | [[package]] 389 | name = "frozenlist" 390 | version = "1.3.3" 391 | description = "A list-like structure which implements collections.abc.MutableSequence" 392 | category = "main" 393 | optional = false 394 | python-versions = ">=3.7" 395 | files = [ 396 | {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4"}, 397 | {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0"}, 398 | {file = "frozenlist-1.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530"}, 399 | {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7"}, 400 | {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99"}, 401 | {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483"}, 402 | {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd"}, 403 | {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf"}, 404 | {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816"}, 405 | {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0"}, 406 | {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce"}, 407 | {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f"}, 408 | {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420"}, 409 | {file = "frozenlist-1.3.3-cp310-cp310-win32.whl", hash = "sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642"}, 410 | {file = "frozenlist-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1"}, 411 | {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7"}, 412 | {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678"}, 413 | {file = "frozenlist-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6"}, 414 | {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8"}, 415 | {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb"}, 416 | {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91"}, 417 | {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b"}, 418 | {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4"}, 419 | {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48"}, 420 | {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d"}, 421 | {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6"}, 422 | {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4"}, 423 | {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81"}, 424 | {file = "frozenlist-1.3.3-cp311-cp311-win32.whl", hash = "sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8"}, 425 | {file = "frozenlist-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32"}, 426 | {file = "frozenlist-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8df3de3a9ab8325f94f646609a66cbeeede263910c5c0de0101079ad541af332"}, 427 | {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0693c609e9742c66ba4870bcee1ad5ff35462d5ffec18710b4ac89337ff16e27"}, 428 | {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd4210baef299717db0a600d7a3cac81d46ef0e007f88c9335db79f8979c0d3d"}, 429 | {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:394c9c242113bfb4b9aa36e2b80a05ffa163a30691c7b5a29eba82e937895d5e"}, 430 | {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6327eb8e419f7d9c38f333cde41b9ae348bec26d840927332f17e887a8dcb70d"}, 431 | {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e24900aa13212e75e5b366cb9065e78bbf3893d4baab6052d1aca10d46d944c"}, 432 | {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3843f84a6c465a36559161e6c59dce2f2ac10943040c2fd021cfb70d58c4ad56"}, 433 | {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:84610c1502b2461255b4c9b7d5e9c48052601a8957cd0aea6ec7a7a1e1fb9420"}, 434 | {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:c21b9aa40e08e4f63a2f92ff3748e6b6c84d717d033c7b3438dd3123ee18f70e"}, 435 | {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:efce6ae830831ab6a22b9b4091d411698145cb9b8fc869e1397ccf4b4b6455cb"}, 436 | {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:40de71985e9042ca00b7953c4f41eabc3dc514a2d1ff534027f091bc74416401"}, 437 | {file = "frozenlist-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:180c00c66bde6146a860cbb81b54ee0df350d2daf13ca85b275123bbf85de18a"}, 438 | {file = "frozenlist-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9bbbcedd75acdfecf2159663b87f1bb5cfc80e7cd99f7ddd9d66eb98b14a8411"}, 439 | {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:034a5c08d36649591be1cbb10e09da9f531034acfe29275fc5454a3b101ce41a"}, 440 | {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba64dc2b3b7b158c6660d49cdb1d872d1d0bf4e42043ad8d5006099479a194e5"}, 441 | {file = "frozenlist-1.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:47df36a9fe24054b950bbc2db630d508cca3aa27ed0566c0baf661225e52c18e"}, 442 | {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008a054b75d77c995ea26629ab3a0c0d7281341f2fa7e1e85fa6153ae29ae99c"}, 443 | {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:841ea19b43d438a80b4de62ac6ab21cfe6827bb8a9dc62b896acc88eaf9cecba"}, 444 | {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e235688f42b36be2b6b06fc37ac2126a73b75fb8d6bc66dd632aa35286238703"}, 445 | {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca713d4af15bae6e5d79b15c10c8522859a9a89d3b361a50b817c98c2fb402a2"}, 446 | {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ac5995f2b408017b0be26d4a1d7c61bce106ff3d9e3324374d66b5964325448"}, 447 | {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4ae8135b11652b08a8baf07631d3ebfe65a4c87909dbef5fa0cdde440444ee4"}, 448 | {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ea42116ceb6bb16dbb7d526e242cb6747b08b7710d9782aa3d6732bd8d27649"}, 449 | {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:810860bb4bdce7557bc0febb84bbd88198b9dbc2022d8eebe5b3590b2ad6c842"}, 450 | {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ee78feb9d293c323b59a6f2dd441b63339a30edf35abcb51187d2fc26e696d13"}, 451 | {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0af2e7c87d35b38732e810befb9d797a99279cbb85374d42ea61c1e9d23094b3"}, 452 | {file = "frozenlist-1.3.3-cp38-cp38-win32.whl", hash = "sha256:899c5e1928eec13fd6f6d8dc51be23f0d09c5281e40d9cf4273d188d9feeaf9b"}, 453 | {file = "frozenlist-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:7f44e24fa70f6fbc74aeec3e971f60a14dde85da364aa87f15d1be94ae75aeef"}, 454 | {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2b07ae0c1edaa0a36339ec6cce700f51b14a3fc6545fdd32930d2c83917332cf"}, 455 | {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ebb86518203e12e96af765ee89034a1dbb0c3c65052d1b0c19bbbd6af8a145e1"}, 456 | {file = "frozenlist-1.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5cf820485f1b4c91e0417ea0afd41ce5cf5965011b3c22c400f6d144296ccbc0"}, 457 | {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c11e43016b9024240212d2a65043b70ed8dfd3b52678a1271972702d990ac6d"}, 458 | {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8fa3c6e3305aa1146b59a09b32b2e04074945ffcfb2f0931836d103a2c38f936"}, 459 | {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:352bd4c8c72d508778cf05ab491f6ef36149f4d0cb3c56b1b4302852255d05d5"}, 460 | {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65a5e4d3aa679610ac6e3569e865425b23b372277f89b5ef06cf2cdaf1ebf22b"}, 461 | {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e2c1185858d7e10ff045c496bbf90ae752c28b365fef2c09cf0fa309291669"}, 462 | {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f163d2fd041c630fed01bc48d28c3ed4a3b003c00acd396900e11ee5316b56bb"}, 463 | {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05cdb16d09a0832eedf770cb7bd1fe57d8cf4eaf5aced29c4e41e3f20b30a784"}, 464 | {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8bae29d60768bfa8fb92244b74502b18fae55a80eac13c88eb0b496d4268fd2d"}, 465 | {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eedab4c310c0299961ac285591acd53dc6723a1ebd90a57207c71f6e0c2153ab"}, 466 | {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3bbdf44855ed8f0fbcd102ef05ec3012d6a4fd7c7562403f76ce6a52aeffb2b1"}, 467 | {file = "frozenlist-1.3.3-cp39-cp39-win32.whl", hash = "sha256:efa568b885bca461f7c7b9e032655c0c143d305bf01c30caf6db2854a4532b38"}, 468 | {file = "frozenlist-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfe33efc9cb900a4c46f91a5ceba26d6df370ffddd9ca386eb1d4f0ad97b9ea9"}, 469 | {file = "frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"}, 470 | ] 471 | 472 | [[package]] 473 | name = "idna" 474 | version = "3.4" 475 | description = "Internationalized Domain Names in Applications (IDNA)" 476 | category = "main" 477 | optional = false 478 | python-versions = ">=3.5" 479 | files = [ 480 | {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, 481 | {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, 482 | ] 483 | 484 | [[package]] 485 | name = "multidict" 486 | version = "6.0.4" 487 | description = "multidict implementation" 488 | category = "main" 489 | optional = false 490 | python-versions = ">=3.7" 491 | files = [ 492 | {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, 493 | {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, 494 | {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, 495 | {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, 496 | {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, 497 | {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, 498 | {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, 499 | {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, 500 | {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, 501 | {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, 502 | {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, 503 | {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, 504 | {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, 505 | {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, 506 | {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, 507 | {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, 508 | {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, 509 | {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, 510 | {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, 511 | {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, 512 | {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, 513 | {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, 514 | {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, 515 | {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, 516 | {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, 517 | {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, 518 | {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, 519 | {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, 520 | {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, 521 | {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, 522 | {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, 523 | {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, 524 | {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, 525 | {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, 526 | {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, 527 | {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, 528 | {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, 529 | {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, 530 | {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, 531 | {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, 532 | {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, 533 | {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, 534 | {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, 535 | {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, 536 | {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, 537 | {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, 538 | {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, 539 | {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, 540 | {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, 541 | {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, 542 | {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, 543 | {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, 544 | {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, 545 | {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, 546 | {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, 547 | {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, 548 | {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, 549 | {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, 550 | {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, 551 | {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, 552 | {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, 553 | {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, 554 | {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, 555 | {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, 556 | {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, 557 | {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, 558 | {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, 559 | {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, 560 | {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, 561 | {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, 562 | {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, 563 | {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, 564 | {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, 565 | {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, 566 | ] 567 | 568 | [[package]] 569 | name = "pycares" 570 | version = "4.3.0" 571 | description = "Python interface for c-ares" 572 | category = "main" 573 | optional = false 574 | python-versions = "*" 575 | files = [ 576 | {file = "pycares-4.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:19c9cdd3322d422931982939773e453e491dfc5c0b2e23d7266959315c7a0824"}, 577 | {file = "pycares-4.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e56e9cdf46a092970dc4b75bbabddea9f480be5eeadc3fcae3eb5c6807c4136"}, 578 | {file = "pycares-4.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c75a6241c79b935048272cb77df498da64b8defc8c4b29fdf9870e43ba4cbb4"}, 579 | {file = "pycares-4.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24d8654fac3742791b8bef59d1fbb3e19ae6a5c48876a6d98659f7c66ee546c4"}, 580 | {file = "pycares-4.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebf50b049a245880f1aa16a6f72c4408e0a65b49ea1d3bf13383a44a2cabd2bf"}, 581 | {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:84daf560962763c0359fd79c750ef480f0fda40c08b57765088dbe362e8dc452"}, 582 | {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:978d10da7ee74b9979c494afa8b646411119ad0186a29c7f13c72bb4295630c6"}, 583 | {file = "pycares-4.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c5b9d7fe52eb3d243f5ead58d5c0011884226d961df8360a34618c38c7515"}, 584 | {file = "pycares-4.3.0-cp310-cp310-win32.whl", hash = "sha256:da7c7089ae617317d2cbe38baefd3821387b3bfef7b3ee5b797b871cb1257974"}, 585 | {file = "pycares-4.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:7106dc683db30e1d851283b7b9df7a5ea4964d6bdd000d918d91d4b1f9bed329"}, 586 | {file = "pycares-4.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4e7a24ecef0b1933f2a3fdbf328d1b529a76cda113f8364fa0742e5b3bd76566"}, 587 | {file = "pycares-4.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7abccc2aa4771c06994e4d9ed596453061e2b8846f887d9c98a64ccdaf4790a"}, 588 | {file = "pycares-4.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531fed46c5ed798a914c3207be4ae7b297c4d09e4183d3cf8fd9ee59a55d5080"}, 589 | {file = "pycares-4.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c9335175af0c64a1e0ba67bdd349eb62d4eea0ad02c235ccdf0d535fd20f323"}, 590 | {file = "pycares-4.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5f0e95535027d2dcd51e780410632b0d3ed7e9e5ceb25dc0fe937f2c2960079"}, 591 | {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3692179ce5fb96908ba342e1e5303608d0c976f0d5d4619fa9d3d6d9d5a9a1b4"}, 592 | {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c4cb6cc7fe8e0606d30b60367f59fe26d1472e88555d61e202db70dea5c8edb"}, 593 | {file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3215445396c74103e2054e6b349d9e85883ceda2006d0039fc2d58c9b11818a2"}, 594 | {file = "pycares-4.3.0-cp311-cp311-win32.whl", hash = "sha256:6a0c0c3a0adf490bba9dbb37dbd07ec81e4a6584f095036ac34f06a633710ffe"}, 595 | {file = "pycares-4.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:995cb37cc39bd40ca87bb16555a0f7724f3be30d9f9059a4caab2fde45b1b903"}, 596 | {file = "pycares-4.3.0-cp36-cp36m-win32.whl", hash = "sha256:4c9187be72449c975c11daa1d94d7ddcc494f8a4c37a6c18f977cd7024a531d9"}, 597 | {file = "pycares-4.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d7405ba10a2903a58b8b0faedcb54994c9ee002ad01963587fabf93e7e479783"}, 598 | {file = "pycares-4.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:40aaa12081495f879f11f4cfc95edfec1ea14711188563102f9e33fe98728fac"}, 599 | {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4972cac24b66c5997f3a3e2cb608e408066d80103d443e36d626a88a287b9ae7"}, 600 | {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35886dba7aa5b73affca8729aeb5a1f5e94d3d9a764adb1b7e75bafca44eeca5"}, 601 | {file = "pycares-4.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5cea6e1f3be016f155d60f27f16c1074d58b4d6e123228fdbc3326d076016af8"}, 602 | {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3a9fd2665b053afb39226ac6f8137a60910ca7729358456df2fb94866f4297de"}, 603 | {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e8e9195f869120e44e0aa0a6098bb5c19947f4753054365891f592e6f9eab3ef"}, 604 | {file = "pycares-4.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:674486ecf2afb25ee219171b07cdaba481a1aaa2dabb155779c7be9ded03eaa9"}, 605 | {file = "pycares-4.3.0-cp37-cp37m-win32.whl", hash = "sha256:1b6cd3161851499b6894d1e23bfd633e7b775472f5af35ae35409c4a47a2d45e"}, 606 | {file = "pycares-4.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:710120c97b9afdba443564350c3f5f72fd9aae74d95b73dc062ca8ac3d7f36d7"}, 607 | {file = "pycares-4.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9103649bd29d84bc6bcfaf09def9c0592bbc766018fad19d76d09989608b915d"}, 608 | {file = "pycares-4.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c072dbaf73cb5434279578dc35322867d8d5df053e14fdcdcc589994ba4804ae"}, 609 | {file = "pycares-4.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008531733f9c7a976b59c7760a3672b191159fd69ae76c01ca051f20b5e44164"}, 610 | {file = "pycares-4.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2aae02d97d77dcff840ab55f86cb8b99bf644acbca17e1edb7048408b9782088"}, 611 | {file = "pycares-4.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:257953ae6d400a934fd9193aeb20990ac84a78648bdf5978e998bd007a4045cd"}, 612 | {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c28d481efae26936ec08cb6beea305f4b145503b152cf2c4dc68cc4ad9644f0e"}, 613 | {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:976249b39037dbfb709ccf7e1c40d2785905a0065536385d501b94570cfed96d"}, 614 | {file = "pycares-4.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:98568c30cfab6b327d94ae1acdf85bbba4cffd415980804985d34ca07e6f4791"}, 615 | {file = "pycares-4.3.0-cp38-cp38-win32.whl", hash = "sha256:a2f3c4f49f43162f7e684419d9834c2c8ec165e54cb8dc47aa9dc0c2132701c0"}, 616 | {file = "pycares-4.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:1730ef93e33e4682fbbf0e7fb19df2ed9822779d17de8ea6e20d5b0d71c1d2be"}, 617 | {file = "pycares-4.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5a26b3f1684557025da26ce65d076619890c82b95e38cc7284ce51c3539a1ce8"}, 618 | {file = "pycares-4.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:86112cce01655b9f63c5e53b74722084e88e784a7a8ad138d373440337c591c9"}, 619 | {file = "pycares-4.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c01465a191dc78e923884bb45cd63c7e012623e520cf7ed67e542413ee334804"}, 620 | {file = "pycares-4.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9fd5d6012f3ee8c8038cbfe16e988bbd17b2f21eea86650874bf63757ee6161"}, 621 | {file = "pycares-4.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa36b8ea91eae20b5c7205f3e6654423f066af24a1df02b274770a96cbcafaa7"}, 622 | {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:61019151130557c1788cae52e4f2f388a7520c9d92574f3a0d61c974c6740db0"}, 623 | {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:231962bb46274c52632469a1e686fab065dbd106dbef586de4f7fb101e297587"}, 624 | {file = "pycares-4.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6c979512fa51c7ccef5204fe10ed4e5c44c2bce5f335fe98a3e423f1672bd7d4"}, 625 | {file = "pycares-4.3.0-cp39-cp39-win32.whl", hash = "sha256:655cf0df862ce3847a60e1a106dafa2ba2c14e6636bac49e874347acdc7312dc"}, 626 | {file = "pycares-4.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:36f2251ad0f99a5ce13df45c94c3161d9734c9e9fa2b9b4cc163b853ca170dc5"}, 627 | {file = "pycares-4.3.0.tar.gz", hash = "sha256:c542696f6dac978e9d99192384745a65f80a7d9450501151e4a7563e06010d45"}, 628 | ] 629 | 630 | [package.dependencies] 631 | cffi = ">=1.5.0" 632 | 633 | [package.extras] 634 | idna = ["idna (>=2.1)"] 635 | 636 | [[package]] 637 | name = "pycparser" 638 | version = "2.21" 639 | description = "C parser in Python" 640 | category = "main" 641 | optional = false 642 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 643 | files = [ 644 | {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, 645 | {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, 646 | ] 647 | 648 | [[package]] 649 | name = "pyee" 650 | version = "9.0.4" 651 | description = "A port of node.js's EventEmitter to python." 652 | category = "main" 653 | optional = false 654 | python-versions = "*" 655 | files = [ 656 | {file = "pyee-9.0.4-py2.py3-none-any.whl", hash = "sha256:9f066570130c554e9cc12de5a9d86f57c7ee47fece163bbdaa3e9c933cfbdfa5"}, 657 | {file = "pyee-9.0.4.tar.gz", hash = "sha256:2770c4928abc721f46b705e6a72b0c59480c4a69c9a83ca0b00bb994f1ea4b32"}, 658 | ] 659 | 660 | [package.dependencies] 661 | typing-extensions = "*" 662 | 663 | [[package]] 664 | name = "pytz" 665 | version = "2022.7.1" 666 | description = "World timezone definitions, modern and historical" 667 | category = "main" 668 | optional = false 669 | python-versions = "*" 670 | files = [ 671 | {file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"}, 672 | {file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"}, 673 | ] 674 | 675 | [[package]] 676 | name = "pytz-deprecation-shim" 677 | version = "0.1.0.post0" 678 | description = "Shims to make deprecation of pytz easier" 679 | category = "main" 680 | optional = false 681 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" 682 | files = [ 683 | {file = "pytz_deprecation_shim-0.1.0.post0-py2.py3-none-any.whl", hash = "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6"}, 684 | {file = "pytz_deprecation_shim-0.1.0.post0.tar.gz", hash = "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"}, 685 | ] 686 | 687 | [package.dependencies] 688 | tzdata = {version = "*", markers = "python_version >= \"3.6\""} 689 | 690 | [[package]] 691 | name = "setuptools" 692 | version = "67.0.0" 693 | description = "Easily download, build, install, upgrade, and uninstall Python packages" 694 | category = "main" 695 | optional = false 696 | python-versions = ">=3.7" 697 | files = [ 698 | {file = "setuptools-67.0.0-py3-none-any.whl", hash = "sha256:9d790961ba6219e9ff7d9557622d2fe136816a264dd01d5997cfc057d804853d"}, 699 | {file = "setuptools-67.0.0.tar.gz", hash = "sha256:883131c5b6efa70b9101c7ef30b2b7b780a4283d5fc1616383cdf22c83cbefe6"}, 700 | ] 701 | 702 | [package.extras] 703 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] 704 | testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] 705 | testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] 706 | 707 | [[package]] 708 | name = "six" 709 | version = "1.16.0" 710 | description = "Python 2 and 3 compatibility utilities" 711 | category = "main" 712 | optional = false 713 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 714 | files = [ 715 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 716 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 717 | ] 718 | 719 | [[package]] 720 | name = "typing-extensions" 721 | version = "4.4.0" 722 | description = "Backported and Experimental Type Hints for Python 3.7+" 723 | category = "main" 724 | optional = false 725 | python-versions = ">=3.7" 726 | files = [ 727 | {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, 728 | {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, 729 | ] 730 | 731 | [[package]] 732 | name = "tzdata" 733 | version = "2022.7" 734 | description = "Provider of IANA time zone data" 735 | category = "main" 736 | optional = false 737 | python-versions = ">=2" 738 | files = [ 739 | {file = "tzdata-2022.7-py2.py3-none-any.whl", hash = "sha256:2b88858b0e3120792a3c0635c23daf36a7d7eeeca657c323da299d2094402a0d"}, 740 | {file = "tzdata-2022.7.tar.gz", hash = "sha256:fe5f866eddd8b96e9fcba978f8e503c909b19ea7efda11e52e39494bad3a7bfa"}, 741 | ] 742 | 743 | [[package]] 744 | name = "tzlocal" 745 | version = "4.2" 746 | description = "tzinfo object for the local timezone" 747 | category = "main" 748 | optional = false 749 | python-versions = ">=3.6" 750 | files = [ 751 | {file = "tzlocal-4.2-py3-none-any.whl", hash = "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745"}, 752 | {file = "tzlocal-4.2.tar.gz", hash = "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"}, 753 | ] 754 | 755 | [package.dependencies] 756 | pytz-deprecation-shim = "*" 757 | tzdata = {version = "*", markers = "platform_system == \"Windows\""} 758 | 759 | [package.extras] 760 | devenv = ["black", "pyroma", "pytest-cov", "zest.releaser"] 761 | test = ["pytest (>=4.3)", "pytest-mock (>=3.3)"] 762 | 763 | [[package]] 764 | name = "yarl" 765 | version = "1.8.2" 766 | description = "Yet another URL library" 767 | category = "main" 768 | optional = false 769 | python-versions = ">=3.7" 770 | files = [ 771 | {file = "yarl-1.8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bb81f753c815f6b8e2ddd2eef3c855cf7da193b82396ac013c661aaa6cc6b0a5"}, 772 | {file = "yarl-1.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:47d49ac96156f0928f002e2424299b2c91d9db73e08c4cd6742923a086f1c863"}, 773 | {file = "yarl-1.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3fc056e35fa6fba63248d93ff6e672c096f95f7836938241ebc8260e062832fe"}, 774 | {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58a3c13d1c3005dbbac5c9f0d3210b60220a65a999b1833aa46bd6677c69b08e"}, 775 | {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10b08293cda921157f1e7c2790999d903b3fd28cd5c208cf8826b3b508026996"}, 776 | {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de986979bbd87272fe557e0a8fcb66fd40ae2ddfe28a8b1ce4eae22681728fef"}, 777 | {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c4fcfa71e2c6a3cb568cf81aadc12768b9995323186a10827beccf5fa23d4f8"}, 778 | {file = "yarl-1.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae4d7ff1049f36accde9e1ef7301912a751e5bae0a9d142459646114c70ecba6"}, 779 | {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bf071f797aec5b96abfc735ab97da9fd8f8768b43ce2abd85356a3127909d146"}, 780 | {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:74dece2bfc60f0f70907c34b857ee98f2c6dd0f75185db133770cd67300d505f"}, 781 | {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:df60a94d332158b444301c7f569659c926168e4d4aad2cfbf4bce0e8fb8be826"}, 782 | {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:63243b21c6e28ec2375f932a10ce7eda65139b5b854c0f6b82ed945ba526bff3"}, 783 | {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cfa2bbca929aa742b5084fd4663dd4b87c191c844326fcb21c3afd2d11497f80"}, 784 | {file = "yarl-1.8.2-cp310-cp310-win32.whl", hash = "sha256:b05df9ea7496df11b710081bd90ecc3a3db6adb4fee36f6a411e7bc91a18aa42"}, 785 | {file = "yarl-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:24ad1d10c9db1953291f56b5fe76203977f1ed05f82d09ec97acb623a7976574"}, 786 | {file = "yarl-1.8.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a1fca9588f360036242f379bfea2b8b44cae2721859b1c56d033adfd5893634"}, 787 | {file = "yarl-1.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f37db05c6051eff17bc832914fe46869f8849de5b92dc4a3466cd63095d23dfd"}, 788 | {file = "yarl-1.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:77e913b846a6b9c5f767b14dc1e759e5aff05502fe73079f6f4176359d832581"}, 789 | {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a"}, 790 | {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388a45dc77198b2460eac0aca1efd6a7c09e976ee768b0d5109173e521a19daf"}, 791 | {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2305517e332a862ef75be8fad3606ea10108662bc6fe08509d5ca99503ac2aee"}, 792 | {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42430ff511571940d51e75cf42f1e4dbdded477e71c1b7a17f4da76c1da8ea76"}, 793 | {file = "yarl-1.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3150078118f62371375e1e69b13b48288e44f6691c1069340081c3fd12c94d5b"}, 794 | {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c15163b6125db87c8f53c98baa5e785782078fbd2dbeaa04c6141935eb6dab7a"}, 795 | {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4d04acba75c72e6eb90745447d69f84e6c9056390f7a9724605ca9c56b4afcc6"}, 796 | {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e7fd20d6576c10306dea2d6a5765f46f0ac5d6f53436217913e952d19237efc4"}, 797 | {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:75c16b2a900b3536dfc7014905a128a2bea8fb01f9ee26d2d7d8db0a08e7cb2c"}, 798 | {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6d88056a04860a98341a0cf53e950e3ac9f4e51d1b6f61a53b0609df342cc8b2"}, 799 | {file = "yarl-1.8.2-cp311-cp311-win32.whl", hash = "sha256:fb742dcdd5eec9f26b61224c23baea46c9055cf16f62475e11b9b15dfd5c117b"}, 800 | {file = "yarl-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c46d3d89902c393a1d1e243ac847e0442d0196bbd81aecc94fcebbc2fd5857c"}, 801 | {file = "yarl-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ceff9722e0df2e0a9e8a79c610842004fa54e5b309fe6d218e47cd52f791d7ef"}, 802 | {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f6b4aca43b602ba0f1459de647af954769919c4714706be36af670a5f44c9c1"}, 803 | {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1684a9bd9077e922300ecd48003ddae7a7474e0412bea38d4631443a91d61077"}, 804 | {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ebb78745273e51b9832ef90c0898501006670d6e059f2cdb0e999494eb1450c2"}, 805 | {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3adeef150d528ded2a8e734ebf9ae2e658f4c49bf413f5f157a470e17a4a2e89"}, 806 | {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57a7c87927a468e5a1dc60c17caf9597161d66457a34273ab1760219953f7f4c"}, 807 | {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:efff27bd8cbe1f9bd127e7894942ccc20c857aa8b5a0327874f30201e5ce83d0"}, 808 | {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a783cd344113cb88c5ff7ca32f1f16532a6f2142185147822187913eb989f739"}, 809 | {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:705227dccbe96ab02c7cb2c43e1228e2826e7ead880bb19ec94ef279e9555b5b"}, 810 | {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:34c09b43bd538bf6c4b891ecce94b6fa4f1f10663a8d4ca589a079a5018f6ed7"}, 811 | {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a48f4f7fea9a51098b02209d90297ac324241bf37ff6be6d2b0149ab2bd51b37"}, 812 | {file = "yarl-1.8.2-cp37-cp37m-win32.whl", hash = "sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89"}, 813 | {file = "yarl-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:d881d152ae0007809c2c02e22aa534e702f12071e6b285e90945aa3c376463c5"}, 814 | {file = "yarl-1.8.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5df5e3d04101c1e5c3b1d69710b0574171cc02fddc4b23d1b2813e75f35a30b1"}, 815 | {file = "yarl-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a66c506ec67eb3159eea5096acd05f5e788ceec7b96087d30c7d2865a243918"}, 816 | {file = "yarl-1.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b4fa2606adf392051d990c3b3877d768771adc3faf2e117b9de7eb977741229"}, 817 | {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e21fb44e1eff06dd6ef971d4bdc611807d6bd3691223d9c01a18cec3677939e"}, 818 | {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93202666046d9edadfe9f2e7bf5e0782ea0d497b6d63da322e541665d65a044e"}, 819 | {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc77086ce244453e074e445104f0ecb27530d6fd3a46698e33f6c38951d5a0f1"}, 820 | {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dd68a92cab699a233641f5929a40f02a4ede8c009068ca8aa1fe87b8c20ae3"}, 821 | {file = "yarl-1.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b372aad2b5f81db66ee7ec085cbad72c4da660d994e8e590c997e9b01e44901"}, 822 | {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e6f3515aafe0209dd17fb9bdd3b4e892963370b3de781f53e1746a521fb39fc0"}, 823 | {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dfef7350ee369197106805e193d420b75467b6cceac646ea5ed3049fcc950a05"}, 824 | {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:728be34f70a190566d20aa13dc1f01dc44b6aa74580e10a3fb159691bc76909d"}, 825 | {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ff205b58dc2929191f68162633d5e10e8044398d7a45265f90a0f1d51f85f72c"}, 826 | {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baf211dcad448a87a0d9047dc8282d7de59473ade7d7fdf22150b1d23859f946"}, 827 | {file = "yarl-1.8.2-cp38-cp38-win32.whl", hash = "sha256:272b4f1599f1b621bf2aabe4e5b54f39a933971f4e7c9aa311d6d7dc06965165"}, 828 | {file = "yarl-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:326dd1d3caf910cd26a26ccbfb84c03b608ba32499b5d6eeb09252c920bcbe4f"}, 829 | {file = "yarl-1.8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f8ca8ad414c85bbc50f49c0a106f951613dfa5f948ab69c10ce9b128d368baf8"}, 830 | {file = "yarl-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:418857f837347e8aaef682679f41e36c24250097f9e2f315d39bae3a99a34cbf"}, 831 | {file = "yarl-1.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ae0eec05ab49e91a78700761777f284c2df119376e391db42c38ab46fd662b77"}, 832 | {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87"}, 833 | {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3edac5d74bb3209c418805bda77f973117836e1de7c000e9755e572c1f7850d0"}, 834 | {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da65c3f263729e47351261351b8679c6429151ef9649bba08ef2528ff2c423b2"}, 835 | {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ef8fb25e52663a1c85d608f6dd72e19bd390e2ecaf29c17fb08f730226e3a08"}, 836 | {file = "yarl-1.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcd7bb1e5c45274af9a1dd7494d3c52b2be5e6bd8d7e49c612705fd45420b12d"}, 837 | {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44ceac0450e648de86da8e42674f9b7077d763ea80c8ceb9d1c3e41f0f0a9951"}, 838 | {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:97209cc91189b48e7cfe777237c04af8e7cc51eb369004e061809bcdf4e55220"}, 839 | {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:48dd18adcf98ea9cd721a25313aef49d70d413a999d7d89df44f469edfb38a06"}, 840 | {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e59399dda559688461762800d7fb34d9e8a6a7444fd76ec33220a926c8be1516"}, 841 | {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d617c241c8c3ad5c4e78a08429fa49e4b04bedfc507b34b4d8dceb83b4af3588"}, 842 | {file = "yarl-1.8.2-cp39-cp39-win32.whl", hash = "sha256:cb6d48d80a41f68de41212f3dfd1a9d9898d7841c8f7ce6696cf2fd9cb57ef83"}, 843 | {file = "yarl-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:6604711362f2dbf7160df21c416f81fac0de6dbcf0b5445a2ef25478ecc4c778"}, 844 | {file = "yarl-1.8.2.tar.gz", hash = "sha256:49d43402c6e3013ad0978602bf6bf5328535c48d192304b91b97a3c6790b1562"}, 845 | ] 846 | 847 | [package.dependencies] 848 | idna = ">=2.0" 849 | multidict = ">=4.0" 850 | 851 | [metadata] 852 | lock-version = "2.0" 853 | python-versions = "^3.10" 854 | content-hash = "f67e5f066d5d8ba0a13d8858cc9224d765eb1df36722e2e4170f723f0fcd83b4" 855 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "blive" 3 | version = "0.2.5" 4 | description = "" 5 | authors = ["Cam "] 6 | license = "MIT" 7 | readme = "README.md" 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.7" 11 | aiohttp = "^3.8.3" 12 | pyee = "^9.0.4" 13 | APScheduler = "^3.9.1.post1" 14 | aiodns = "^3.0.0" 15 | brotli = "^1.0.9" 16 | 17 | 18 | [build-system] 19 | requires = ["poetry-core"] 20 | build-backend = "poetry.core.masonry.api" 21 | --------------------------------------------------------------------------------