🎨 优化连接稳定性

This commit is contained in:
Wuyi无疑 2023-04-16 00:28:23 +08:00
parent b43dd38b1d
commit fbddc24f3d
5 changed files with 226 additions and 19 deletions

View File

@ -11,11 +11,16 @@ from nonebot.adapters import Bot
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.permission import SUPERUSER from nonebot.permission import SUPERUSER
from nonebot.internal.adapter import Event from nonebot.internal.adapter import Event
from nonebot import on_notice, get_driver, on_message, on_fullmatch from websockets.exceptions import ConnectionClosed
from nonebot import require, on_notice, on_message, on_fullmatch
from .client import GsClient require('nonebot_plugin_apscheduler')
from .auto_install import start, install
from .models import Message, MessageReceive from nonebot_plugin_apscheduler import scheduler # noqa:E402
from .client import GsClient, driver # noqa:E402
from .auto_install import start, install # noqa:E402
from .models import Message, MessageReceive # noqa:E402
get_message = on_message(priority=999) get_message = on_message(priority=999)
get_notice = on_notice(priority=999) get_notice = on_notice(priority=999)
@ -24,15 +29,24 @@ start_core = on_fullmatch('启动core', permission=SUPERUSER, block=True)
connect_core = on_fullmatch( connect_core = on_fullmatch(
('连接core', '链接core'), permission=SUPERUSER, block=True ('连接core', '链接core'), permission=SUPERUSER, block=True
) )
driver = get_driver()
gsclient: Optional[GsClient] = None
gsclient: Optional[GsClient] = None
command_start = driver.config.command_start command_start = driver.config.command_start
if hasattr(driver.config, 'gsuid_core_repeat'):
is_repeat = True
else:
is_repeat = False
@get_notice.handle() @get_notice.handle()
async def get_notice_message(bot: Bot, ev: Event): async def get_notice_message(bot: Bot, ev: Event):
if gsclient is None or not gsclient.is_alive: if gsclient is None:
return await connect()
try:
await gsclient.ws.ping()
except ConnectionClosed:
return await connect() return await connect()
raw_data = ev.dict() raw_data = ev.dict()
@ -377,11 +391,24 @@ async def connect():
global gsclient global gsclient
try: try:
gsclient = await GsClient().async_connect() gsclient = await GsClient().async_connect()
await gsclient.start()
except ConnectionRefusedError: except ConnectionRefusedError:
logger.error('Core服务器连接失败...请稍后使用[启动core]命令启动...') logger.error('Core服务器连接失败...请稍后使用[启动core]命令启动...')
@scheduler.scheduled_job('cron', second='*/10')
async def repeat_connect():
if is_repeat:
global gsclient
if gsclient is None:
await connect()
else:
try:
await gsclient.ws.ensure_open()
except ConnectionClosed:
return await connect()
return
def convert_message(_msg: Any, message: List[Message], index: int): def convert_message(_msg: Any, message: List[Message], index: int):
if _msg.type == 'text': if _msg.type == 'text':
data: str = ( data: str = (

View File

@ -1,6 +1,7 @@
import os import os
import json import json
import time import time
import uuid
import base64 import base64
import asyncio import asyncio
from pathlib import Path from pathlib import Path
@ -15,10 +16,14 @@ from websockets.exceptions import ConnectionClosedError
from .models import MessageSend, MessageReceive from .models import MessageSend, MessageReceive
BOT_ID = 'NoneBot2'
bots: Dict[str, str] = {} bots: Dict[str, str] = {}
driver = get_driver() driver = get_driver()
if hasattr(driver.config, 'gsuid_core_botid'):
BOT_ID = str(uuid.uuid4())[:10]
else:
BOT_ID = 'NoneBot2'
if hasattr(driver.config, 'gsuid_core_host'): if hasattr(driver.config, 'gsuid_core_host'):
HOST = driver.config.gsuid_core_host HOST = driver.config.gsuid_core_host
else: else:
@ -44,6 +49,8 @@ def _get_bot(bot_id: str) -> Bot:
class GsClient: class GsClient:
_instance = None
@classmethod @classmethod
async def async_connect(cls, IP: str = HOST, PORT: Union[str, int] = PORT): async def async_connect(cls, IP: str = HOST, PORT: Union[str, int] = PORT):
self = GsClient() self = GsClient()
@ -55,8 +62,16 @@ class GsClient:
) )
logger.success(f'与[gsuid-core]成功连接! Bot_ID: {BOT_ID}') logger.success(f'与[gsuid-core]成功连接! Bot_ID: {BOT_ID}')
cls.msg_list = asyncio.queues.Queue() cls.msg_list = asyncio.queues.Queue()
cls.pending = []
await self.start()
return self return self
def __new__(cls, *args, **kwargs):
# 判断sv是否已经被初始化
if cls._instance is None:
cls._instance = super(GsClient, cls).__new__(cls, *args, **kwargs)
return cls._instance
async def recv_msg(self): async def recv_msg(self):
try: try:
global bots global bots
@ -199,8 +214,17 @@ class GsClient:
except RuntimeError as e: except RuntimeError as e:
logger.error(e) logger.error(e)
except ConnectionClosedError: except ConnectionClosedError:
for task in self.pending:
task.cancel()
logger.warning(f'与[gsuid-core]断开连接! Bot_ID: {BOT_ID}') logger.warning(f'与[gsuid-core]断开连接! Bot_ID: {BOT_ID}')
self.is_alive = False for _ in range(30):
await asyncio.sleep(5)
try:
await self.async_connect()
await self.start()
break
except: # noqa
logger.debug('自动连接core服务器失败...五秒后重新连接...')
async def _input(self, msg: MessageReceive): async def _input(self, msg: MessageReceive):
await self.msg_list.put(msg) await self.msg_list.put(msg)
@ -214,12 +238,10 @@ class GsClient:
async def start(self): async def start(self):
recv_task = asyncio.create_task(self.recv_msg()) recv_task = asyncio.create_task(self.recv_msg())
send_task = asyncio.create_task(self.send_msg()) send_task = asyncio.create_task(self.send_msg())
_, pending = await asyncio.wait( _, self.pending = await asyncio.wait(
[recv_task, send_task], [recv_task, send_task],
return_when=asyncio.FIRST_COMPLETED, return_when=asyncio.FIRST_COMPLETED,
) )
for task in pending:
task.cancel()
def to_json(msg: str, name: str, uin: int): def to_json(msg: str, name: str, uin: int):
@ -252,9 +274,10 @@ async def onebot_send(
): ):
async def _send(content: Optional[str], image: Optional[str]): async def _send(content: Optional[str], image: Optional[str]):
from nonebot.adapters.onebot.v11 import MessageSegment from nonebot.adapters.onebot.v11 import MessageSegment
result_image = MessageSegment.image(image) if image else '' result_image = MessageSegment.image(image) if image else ''
content = MessageSegment.text(content) if content else '' _content = MessageSegment.text(content) if content else ''
result_msg = content + result_image result_msg = _content + result_image
if at_list and target_type == 'group': if at_list and target_type == 'group':
for at in at_list: for at in at_list:
result_msg += MessageSegment.at(at) result_msg += MessageSegment.at(at)

153
poetry.lock generated
View File

@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry and should not be changed by hand. # This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand.
[[package]] [[package]]
name = "aiofiles" name = "aiofiles"
@ -12,6 +12,65 @@ files = [
{file = "aiofiles-23.1.0.tar.gz", hash = "sha256:edd247df9a19e0db16534d4baaf536d6609a43e1de5401d7a4c1c148753a1635"}, {file = "aiofiles-23.1.0.tar.gz", hash = "sha256:edd247df9a19e0db16534d4baaf536d6609a43e1de5401d7a4c1c148753a1635"},
] ]
[[package]]
name = "apscheduler"
version = "3.10.1"
description = "In-process task scheduler with Cron-like capabilities"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "APScheduler-3.10.1-py3-none-any.whl", hash = "sha256:e813ad5ada7aff36fb08cdda746b520531eaac7757832abc204868ba78e0c8f6"},
{file = "APScheduler-3.10.1.tar.gz", hash = "sha256:0293937d8f6051a0f493359440c1a1b93e882c57daf0197afeff0e727777b96e"},
]
[package.dependencies]
pytz = "*"
setuptools = ">=0.7"
six = ">=1.4.0"
tzlocal = ">=2.0,<3.0.0 || >=4.0.0"
[package.extras]
doc = ["sphinx", "sphinx-rtd-theme"]
gevent = ["gevent"]
mongodb = ["pymongo (>=3.0)"]
redis = ["redis (>=3.0)"]
rethinkdb = ["rethinkdb (>=2.4.0)"]
sqlalchemy = ["sqlalchemy (>=1.4)"]
testing = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-tornado5"]
tornado = ["tornado (>=4.3)"]
twisted = ["twisted"]
zookeeper = ["kazoo"]
[[package]]
name = "backports-zoneinfo"
version = "0.2.1"
description = "Backport of the standard library zoneinfo module"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
{file = "backports.zoneinfo-0.2.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc"},
{file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722"},
{file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546"},
{file = "backports.zoneinfo-0.2.1-cp36-cp36m-win32.whl", hash = "sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08"},
{file = "backports.zoneinfo-0.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7"},
{file = "backports.zoneinfo-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac"},
{file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf"},
{file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570"},
{file = "backports.zoneinfo-0.2.1-cp37-cp37m-win32.whl", hash = "sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b"},
{file = "backports.zoneinfo-0.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582"},
{file = "backports.zoneinfo-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987"},
{file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1"},
{file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9"},
{file = "backports.zoneinfo-0.2.1-cp38-cp38-win32.whl", hash = "sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328"},
{file = "backports.zoneinfo-0.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6"},
{file = "backports.zoneinfo-0.2.1.tar.gz", hash = "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"},
]
[package.extras]
tzdata = ["tzdata"]
[[package]] [[package]]
name = "black" name = "black"
version = "22.12.0" version = "22.12.0"
@ -443,6 +502,22 @@ files = [
[package.dependencies] [package.dependencies]
setuptools = "*" setuptools = "*"
[[package]]
name = "nonebot-plugin-apscheduler"
version = "0.2.0"
description = "APScheduler Support for NoneBot2"
category = "main"
optional = false
python-versions = ">=3.8,<4.0"
files = [
{file = "nonebot-plugin-apscheduler-0.2.0.tar.gz", hash = "sha256:7b63e99a611b657533b48fcf1f8c6627c18c2eb3fa820a906cd4ec4666c0ceb0"},
{file = "nonebot_plugin_apscheduler-0.2.0-py3-none-any.whl", hash = "sha256:9285ee84ca1cfa4db73c86cedb5911bbbd25a21ec0cd5f22447cd12f89e48fb4"},
]
[package.dependencies]
apscheduler = ">=3.7.0,<4.0.0"
nonebot2 = ">=2.0.0-rc.1,<3.0.0"
[[package]] [[package]]
name = "nonebot2" name = "nonebot2"
version = "2.0.0rc4" version = "2.0.0rc4"
@ -722,6 +797,34 @@ files = [
[package.extras] [package.extras]
cli = ["click (>=5.0)"] cli = ["click (>=5.0)"]
[[package]]
name = "pytz"
version = "2023.3"
description = "World timezone definitions, modern and historical"
category = "main"
optional = false
python-versions = "*"
files = [
{file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
{file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
]
[[package]]
name = "pytz-deprecation-shim"
version = "0.1.0.post0"
description = "Shims to make deprecation of pytz easier"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [
{file = "pytz_deprecation_shim-0.1.0.post0-py2.py3-none-any.whl", hash = "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6"},
{file = "pytz_deprecation_shim-0.1.0.post0.tar.gz", hash = "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"},
]
[package.dependencies]
"backports.zoneinfo" = {version = "*", markers = "python_version >= \"3.6\" and python_version < \"3.9\""}
tzdata = {version = "*", markers = "python_version >= \"3.6\""}
[[package]] [[package]]
name = "pyyaml" name = "pyyaml"
version = "6.0" version = "6.0"
@ -776,7 +879,7 @@ files = [
name = "setuptools" name = "setuptools"
version = "67.6.1" version = "67.6.1"
description = "Easily download, build, install, upgrade, and uninstall Python packages" description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "dev" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
@ -789,6 +892,18 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-g
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"] 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"]
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"] 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"]
[[package]]
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
[[package]] [[package]]
name = "smmap" name = "smmap"
version = "5.0.0" version = "5.0.0"
@ -874,6 +989,38 @@ files = [
mypy-extensions = ">=0.3.0" mypy-extensions = ">=0.3.0"
typing-extensions = ">=3.7.4" typing-extensions = ">=3.7.4"
[[package]]
name = "tzdata"
version = "2023.3"
description = "Provider of IANA time zone data"
category = "main"
optional = false
python-versions = ">=2"
files = [
{file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"},
{file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"},
]
[[package]]
name = "tzlocal"
version = "4.3"
description = "tzinfo object for the local timezone"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "tzlocal-4.3-py3-none-any.whl", hash = "sha256:b44c4388f3d34f25862cfbb387578a4d70fec417649da694a132f628a23367e2"},
{file = "tzlocal-4.3.tar.gz", hash = "sha256:3f21d09e1b2aa9f2dacca12da240ca37de3ba5237a93addfd6d593afe9073355"},
]
[package.dependencies]
"backports.zoneinfo" = {version = "*", markers = "python_version < \"3.9\""}
pytz-deprecation-shim = "*"
tzdata = {version = "*", markers = "platform_system == \"Windows\""}
[package.extras]
devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"]
[[package]] [[package]]
name = "virtualenv" name = "virtualenv"
version = "20.21.0" version = "20.21.0"
@ -1081,4 +1228,4 @@ multidict = ">=4.0"
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.8.1" python-versions = "^3.8.1"
content-hash = "d49e84b5eb2a29ca82a116c6fb3887eb5e5a4c634c9813aeccef8edfe1cdb5e8" content-hash = "018ab686902eb17df6a5280eb1366aed1ba69999257a0741ef2fbcbe766533d6"

View File

@ -23,7 +23,7 @@ build-backend = "poetry.core.masonry.api"
[tool.poetry] [tool.poetry]
name = "nonebot-plugin-genshinuid" name = "nonebot-plugin-genshinuid"
version = "4.0.2" version = "4.0.3"
description = "支持OneBot(QQ)、OneBotV12、QQ频道、微信、KOOK开黑啦、Telegram电报、FeiShu飞书的全功能NoneBot2原神插件" description = "支持OneBot(QQ)、OneBotV12、QQ频道、微信、KOOK开黑啦、Telegram电报、FeiShu飞书的全功能NoneBot2原神插件"
authors = ["KimigaiiWuyi <444835641@qq.com>"] authors = ["KimigaiiWuyi <444835641@qq.com>"]
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
@ -47,6 +47,7 @@ gitpython = ">=3.1.27"
msgspec = ">=0.13.1" msgspec = ">=0.13.1"
aiofiles = ">=23.1.0" aiofiles = ">=23.1.0"
websockets = ">=11.0.1" websockets = ">=11.0.1"
nonebot-plugin-apscheduler = "^0.2.0"
[[tool.poetry.source]] [[tool.poetry.source]]
name = "USTC" name = "USTC"

View File

@ -1,4 +1,6 @@
aiofiles==23.1.0 ; python_full_version >= "3.8.1" and python_version < "4.0" aiofiles==23.1.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
apscheduler==3.10.1 ; python_full_version >= "3.8.1" and python_version < "4.0"
backports-zoneinfo==0.2.1 ; python_full_version >= "3.8.1" and python_version < "3.9"
colorama==0.4.6 ; python_full_version >= "3.8.1" and python_version < "4.0" and sys_platform == "win32" colorama==0.4.6 ; python_full_version >= "3.8.1" and python_version < "4.0" and sys_platform == "win32"
gitdb==4.0.10 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" gitdb==4.0.10 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
gitpython==3.1.31 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" gitpython==3.1.31 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
@ -6,14 +8,21 @@ idna==3.4 ; python_full_version >= "3.8.1" and python_version < "4.0"
loguru==0.6.0 ; python_full_version >= "3.8.1" and python_version < "4.0" loguru==0.6.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
msgspec==0.14.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" msgspec==0.14.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
multidict==6.0.4 ; python_full_version >= "3.8.1" and python_version < "4.0" multidict==6.0.4 ; python_full_version >= "3.8.1" and python_version < "4.0"
nonebot-plugin-apscheduler==0.2.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
nonebot2==2.0.0rc4 ; python_full_version >= "3.8.1" and python_version < "4.0" nonebot2==2.0.0rc4 ; python_full_version >= "3.8.1" and python_version < "4.0"
pillow==9.5.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" pillow==9.5.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
pydantic[dotenv]==1.10.7 ; python_full_version >= "3.8.1" and python_version < "4.0" pydantic[dotenv]==1.10.7 ; python_full_version >= "3.8.1" and python_version < "4.0"
pygtrie==2.5.0 ; python_full_version >= "3.8.1" and python_version < "4.0" pygtrie==2.5.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
python-dotenv==1.0.0 ; python_full_version >= "3.8.1" and python_version < "4.0" python-dotenv==1.0.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
pytz-deprecation-shim==0.1.0.post0 ; python_full_version >= "3.8.1" and python_version < "4.0"
pytz==2023.3 ; python_full_version >= "3.8.1" and python_version < "4.0"
setuptools==67.6.1 ; python_full_version >= "3.8.1" and python_version < "4.0"
six==1.16.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
smmap==5.0.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" smmap==5.0.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
tomli==2.0.1 ; python_full_version >= "3.8.1" and python_version < "3.11" tomli==2.0.1 ; python_full_version >= "3.8.1" and python_version < "3.11"
typing-extensions==4.5.0 ; python_full_version >= "3.8.1" and python_version < "4.0" typing-extensions==4.5.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
tzdata==2023.3 ; python_full_version >= "3.8.1" and python_version < "4.0"
tzlocal==4.3 ; python_full_version >= "3.8.1" and python_version < "4.0"
websockets==11.0.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" websockets==11.0.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
win32-setctime==1.1.0 ; python_full_version >= "3.8.1" and python_version < "4.0" and sys_platform == "win32" win32-setctime==1.1.0 ; python_full_version >= "3.8.1" and python_version < "4.0" and sys_platform == "win32"
yarl==1.8.2 ; python_full_version >= "3.8.1" and python_version < "4.0" yarl==1.8.2 ; python_full_version >= "3.8.1" and python_version < "4.0"