♻️ Use persica refactor code

This commit is contained in:
xtaodada 2024-09-21 00:10:00 +08:00
parent 664a47ad6e
commit 3006d6e667
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
23 changed files with 1207 additions and 273 deletions

1
.gitignore vendored
View File

@ -163,3 +163,4 @@ cython_debug/
cache/
data/
docker-compose.yml
.pdm-python

66
main.py
View File

@ -1,58 +1,18 @@
import asyncio
from signal import signal as signal_fn, SIGINT, SIGTERM, SIGABRT
from src.app import web
from src.bot import bot
from src.env import MIYOUSHE, HOYOLAB, BOT
from persica.context.application import ApplicationContext
from persica.applicationbuilder import ApplicationBuilder
async def idle():
task = None
def signal_handler(_, __):
if web.web_server_task:
web.web_server_task.cancel()
task.cancel()
for s in (SIGINT, SIGTERM, SIGABRT):
signal_fn(s, signal_handler)
while True:
task = asyncio.create_task(asyncio.sleep(600))
web.bot_main_task = task
try:
await task
except asyncio.CancelledError:
break
async def main():
if MIYOUSHE:
from src.render.article import refresh_recommend_posts
await refresh_recommend_posts()
if HOYOLAB:
from src.render.article_hoyolab import refresh_hoyo_recommend_posts
await refresh_hoyo_recommend_posts()
await web.start()
if BOT:
await bot.start()
try:
await idle()
finally:
if BOT:
try:
await bot.stop()
except RuntimeError:
pass
if web.web_server:
try:
await web.web_server.shutdown()
except AttributeError:
pass
def main():
app = (
ApplicationBuilder()
.set_application_context_class(ApplicationContext)
.set_scanner_packages("src/core")
.build()
)
app.class_scanner.flash("src/plugins")
app.class_scanner.flash("src/route")
app.run()
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
main()

840
pdm.lock Normal file
View File

@ -0,0 +1,840 @@
# This file is @generated by PDM.
# It is not intended for manual editing.
[metadata]
groups = ["default", "test"]
strategy = ["inherit_metadata"]
lock_version = "4.5.0"
content_hash = "sha256:268dec44f0ecec5ed8bcdf7cbe20bb3d7b945f16196c3ff5ec721cd01dc19be0"
[[metadata.targets]]
requires_python = ">=3.10"
[[package]]
name = "aiofiles"
version = "24.1.0"
requires_python = ">=3.8"
summary = "File support for asyncio."
groups = ["default"]
files = [
{file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"},
{file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"},
]
[[package]]
name = "annotated-types"
version = "0.7.0"
requires_python = ">=3.8"
summary = "Reusable constraint types to use with typing.Annotated"
groups = ["default"]
dependencies = [
"typing-extensions>=4.0.0; python_version < \"3.9\"",
]
files = [
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
]
[[package]]
name = "anyio"
version = "4.5.0"
requires_python = ">=3.8"
summary = "High level compatibility layer for multiple asynchronous event loop implementations"
groups = ["default"]
dependencies = [
"exceptiongroup>=1.0.2; python_version < \"3.11\"",
"idna>=2.8",
"sniffio>=1.1",
"typing-extensions>=4.1; python_version < \"3.11\"",
]
files = [
{file = "anyio-4.5.0-py3-none-any.whl", hash = "sha256:fdeb095b7cc5a5563175eedd926ec4ae55413bb4be5770c424af0ba46ccb4a78"},
{file = "anyio-4.5.0.tar.gz", hash = "sha256:c5a275fe5ca0afd788001f58fca1e69e29ce706d746e317d660e21f70c530ef9"},
]
[[package]]
name = "apscheduler"
version = "3.10.4"
requires_python = ">=3.6"
summary = "In-process task scheduler with Cron-like capabilities"
groups = ["default"]
dependencies = [
"importlib-metadata>=3.6.0; python_version < \"3.8\"",
"pytz",
"six>=1.4.0",
"tzlocal!=3.*,>=2.0",
]
files = [
{file = "APScheduler-3.10.4-py3-none-any.whl", hash = "sha256:fb91e8a768632a4756a585f79ec834e0e27aad5860bac7eaa523d9ccefd87661"},
{file = "APScheduler-3.10.4.tar.gz", hash = "sha256:e6df071b27d9be898e486bc7940a7be50b4af2e9da7c08f0744a96d4bd4cef4a"},
]
[[package]]
name = "beautifulsoup4"
version = "4.12.3"
requires_python = ">=3.6.0"
summary = "Screen-scraping library"
groups = ["default"]
dependencies = [
"soupsieve>1.2",
]
files = [
{file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"},
{file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"},
]
[[package]]
name = "certifi"
version = "2024.8.30"
requires_python = ">=3.6"
summary = "Python package for providing Mozilla's CA Bundle."
groups = ["default"]
files = [
{file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
{file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
]
[[package]]
name = "click"
version = "8.1.7"
requires_python = ">=3.7"
summary = "Composable command line interface toolkit"
groups = ["default"]
dependencies = [
"colorama; platform_system == \"Windows\"",
"importlib-metadata; python_version < \"3.8\"",
]
files = [
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
]
[[package]]
name = "colorama"
version = "0.4.6"
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
summary = "Cross-platform colored terminal text."
groups = ["default", "test"]
marker = "sys_platform == \"win32\" or platform_system == \"Windows\""
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "coloredlogs"
version = "15.0.1"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
summary = "Colored terminal output for Python's logging module"
groups = ["default"]
dependencies = [
"humanfriendly>=9.1",
]
files = [
{file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"},
{file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"},
]
[[package]]
name = "exceptiongroup"
version = "1.2.2"
requires_python = ">=3.7"
summary = "Backport of PEP 654 (exception groups)"
groups = ["default", "test"]
marker = "python_version < \"3.11\""
files = [
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
]
[[package]]
name = "fastapi"
version = "0.115.0"
requires_python = ">=3.8"
summary = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
groups = ["default"]
dependencies = [
"pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4",
"starlette<0.39.0,>=0.37.2",
"typing-extensions>=4.8.0",
]
files = [
{file = "fastapi-0.115.0-py3-none-any.whl", hash = "sha256:17ea427674467486e997206a5ab25760f6b09e069f099b96f5b55a32fb6f1631"},
{file = "fastapi-0.115.0.tar.gz", hash = "sha256:f93b4ca3529a8ebc6fc3fcf710e5efa8de3df9b41570958abf1d97d843138004"},
]
[[package]]
name = "filelock"
version = "3.16.1"
requires_python = ">=3.8"
summary = "A platform independent file lock."
groups = ["default"]
files = [
{file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"},
{file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"},
]
[[package]]
name = "h11"
version = "0.14.0"
requires_python = ">=3.7"
summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
groups = ["default"]
dependencies = [
"typing-extensions; python_version < \"3.8\"",
]
files = [
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
]
[[package]]
name = "httpcore"
version = "1.0.5"
requires_python = ">=3.8"
summary = "A minimal low-level HTTP client."
groups = ["default"]
dependencies = [
"certifi",
"h11<0.15,>=0.13",
]
files = [
{file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"},
{file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"},
]
[[package]]
name = "httpx"
version = "0.27.2"
requires_python = ">=3.8"
summary = "The next generation HTTP client."
groups = ["default"]
dependencies = [
"anyio",
"certifi",
"httpcore==1.*",
"idna",
"sniffio",
]
files = [
{file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"},
{file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"},
]
[[package]]
name = "humanfriendly"
version = "10.0"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
summary = "Human friendly output for text interfaces using Python"
groups = ["default"]
dependencies = [
"monotonic; python_version == \"2.7\"",
"pyreadline3; sys_platform == \"win32\" and python_version >= \"3.8\"",
"pyreadline; sys_platform == \"win32\" and python_version < \"3.8\"",
]
files = [
{file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"},
{file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"},
]
[[package]]
name = "idna"
version = "3.10"
requires_python = ">=3.6"
summary = "Internationalized Domain Names in Applications (IDNA)"
groups = ["default"]
files = [
{file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
{file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
]
[[package]]
name = "iniconfig"
version = "2.0.0"
requires_python = ">=3.7"
summary = "brain-dead simple config-ini parsing"
groups = ["test"]
files = [
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
[[package]]
name = "jinja2"
version = "3.1.4"
requires_python = ">=3.7"
summary = "A very fast and expressive template engine."
groups = ["default"]
dependencies = [
"MarkupSafe>=2.0",
]
files = [
{file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
{file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
]
[[package]]
name = "lxml"
version = "5.3.0"
requires_python = ">=3.6"
summary = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
groups = ["default"]
files = [
{file = "lxml-5.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:dd36439be765e2dde7660212b5275641edbc813e7b24668831a5c8ac91180656"},
{file = "lxml-5.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ae5fe5c4b525aa82b8076c1a59d642c17b6e8739ecf852522c6321852178119d"},
{file = "lxml-5.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:501d0d7e26b4d261fca8132854d845e4988097611ba2531408ec91cf3fd9d20a"},
{file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66442c2546446944437df74379e9cf9e9db353e61301d1a0e26482f43f0dd8"},
{file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e41506fec7a7f9405b14aa2d5c8abbb4dbbd09d88f9496958b6d00cb4d45330"},
{file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f7d4a670107d75dfe5ad080bed6c341d18c4442f9378c9f58e5851e86eb79965"},
{file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41ce1f1e2c7755abfc7e759dc34d7d05fd221723ff822947132dc934d122fe22"},
{file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:44264ecae91b30e5633013fb66f6ddd05c006d3e0e884f75ce0b4755b3e3847b"},
{file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:3c174dc350d3ec52deb77f2faf05c439331d6ed5e702fc247ccb4e6b62d884b7"},
{file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:2dfab5fa6a28a0b60a20638dc48e6343c02ea9933e3279ccb132f555a62323d8"},
{file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b1c8c20847b9f34e98080da785bb2336ea982e7f913eed5809e5a3c872900f32"},
{file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2c86bf781b12ba417f64f3422cfc302523ac9cd1d8ae8c0f92a1c66e56ef2e86"},
{file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c162b216070f280fa7da844531169be0baf9ccb17263cf5a8bf876fcd3117fa5"},
{file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:36aef61a1678cb778097b4a6eeae96a69875d51d1e8f4d4b491ab3cfb54b5a03"},
{file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f65e5120863c2b266dbcc927b306c5b78e502c71edf3295dfcb9501ec96e5fc7"},
{file = "lxml-5.3.0-cp310-cp310-win32.whl", hash = "sha256:ef0c1fe22171dd7c7c27147f2e9c3e86f8bdf473fed75f16b0c2e84a5030ce80"},
{file = "lxml-5.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:052d99051e77a4f3e8482c65014cf6372e61b0a6f4fe9edb98503bb5364cfee3"},
{file = "lxml-5.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74bcb423462233bc5d6066e4e98b0264e7c1bed7541fff2f4e34fe6b21563c8b"},
{file = "lxml-5.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a3d819eb6f9b8677f57f9664265d0a10dd6551d227afb4af2b9cd7bdc2ccbf18"},
{file = "lxml-5.3.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b8f5db71b28b8c404956ddf79575ea77aa8b1538e8b2ef9ec877945b3f46442"},
{file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3406b63232fc7e9b8783ab0b765d7c59e7c59ff96759d8ef9632fca27c7ee4"},
{file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ecdd78ab768f844c7a1d4a03595038c166b609f6395e25af9b0f3f26ae1230f"},
{file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168f2dfcfdedf611eb285efac1516c8454c8c99caf271dccda8943576b67552e"},
{file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa617107a410245b8660028a7483b68e7914304a6d4882b5ff3d2d3eb5948d8c"},
{file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:69959bd3167b993e6e710b99051265654133a98f20cec1d9b493b931942e9c16"},
{file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:bd96517ef76c8654446fc3db9242d019a1bb5fe8b751ba414765d59f99210b79"},
{file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:ab6dd83b970dc97c2d10bc71aa925b84788c7c05de30241b9e96f9b6d9ea3080"},
{file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eec1bb8cdbba2925bedc887bc0609a80e599c75b12d87ae42ac23fd199445654"},
{file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a7095eeec6f89111d03dabfe5883a1fd54da319c94e0fb104ee8f23616b572d"},
{file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6f651ebd0b21ec65dfca93aa629610a0dbc13dbc13554f19b0113da2e61a4763"},
{file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:f422a209d2455c56849442ae42f25dbaaba1c6c3f501d58761c619c7836642ec"},
{file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:62f7fdb0d1ed2065451f086519865b4c90aa19aed51081979ecd05a21eb4d1be"},
{file = "lxml-5.3.0-cp311-cp311-win32.whl", hash = "sha256:c6379f35350b655fd817cd0d6cbeef7f265f3ae5fedb1caae2eb442bbeae9ab9"},
{file = "lxml-5.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c52100e2c2dbb0649b90467935c4b0de5528833c76a35ea1a2691ec9f1ee7a1"},
{file = "lxml-5.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e99f5507401436fdcc85036a2e7dc2e28d962550afe1cbfc07c40e454256a859"},
{file = "lxml-5.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:384aacddf2e5813a36495233b64cb96b1949da72bef933918ba5c84e06af8f0e"},
{file = "lxml-5.3.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a216bf6afaf97c263b56371434e47e2c652d215788396f60477540298218f"},
{file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65ab5685d56914b9a2a34d67dd5488b83213d680b0c5d10b47f81da5a16b0b0e"},
{file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aac0bbd3e8dd2d9c45ceb82249e8bdd3ac99131a32b4d35c8af3cc9db1657179"},
{file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b369d3db3c22ed14c75ccd5af429086f166a19627e84a8fdade3f8f31426e52a"},
{file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c24037349665434f375645fa9d1f5304800cec574d0310f618490c871fd902b3"},
{file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:62d172f358f33a26d6b41b28c170c63886742f5b6772a42b59b4f0fa10526cb1"},
{file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:c1f794c02903c2824fccce5b20c339a1a14b114e83b306ff11b597c5f71a1c8d"},
{file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:5d6a6972b93c426ace71e0be9a6f4b2cfae9b1baed2eed2006076a746692288c"},
{file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:3879cc6ce938ff4eb4900d901ed63555c778731a96365e53fadb36437a131a99"},
{file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:74068c601baff6ff021c70f0935b0c7bc528baa8ea210c202e03757c68c5a4ff"},
{file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ecd4ad8453ac17bc7ba3868371bffb46f628161ad0eefbd0a855d2c8c32dd81a"},
{file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7e2f58095acc211eb9d8b5771bf04df9ff37d6b87618d1cbf85f92399c98dae8"},
{file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e63601ad5cd8f860aa99d109889b5ac34de571c7ee902d6812d5d9ddcc77fa7d"},
{file = "lxml-5.3.0-cp312-cp312-win32.whl", hash = "sha256:17e8d968d04a37c50ad9c456a286b525d78c4a1c15dd53aa46c1d8e06bf6fa30"},
{file = "lxml-5.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:c1a69e58a6bb2de65902051d57fde951febad631a20a64572677a1052690482f"},
{file = "lxml-5.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c72e9563347c7395910de6a3100a4840a75a6f60e05af5e58566868d5eb2d6a"},
{file = "lxml-5.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e92ce66cd919d18d14b3856906a61d3f6b6a8500e0794142338da644260595cd"},
{file = "lxml-5.3.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d04f064bebdfef9240478f7a779e8c5dc32b8b7b0b2fc6a62e39b928d428e51"},
{file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c2fb570d7823c2bbaf8b419ba6e5662137f8166e364a8b2b91051a1fb40ab8b"},
{file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c120f43553ec759f8de1fee2f4794452b0946773299d44c36bfe18e83caf002"},
{file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:562e7494778a69086f0312ec9689f6b6ac1c6b65670ed7d0267e49f57ffa08c4"},
{file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:423b121f7e6fa514ba0c7918e56955a1d4470ed35faa03e3d9f0e3baa4c7e492"},
{file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c00f323cc00576df6165cc9d21a4c21285fa6b9989c5c39830c3903dc4303ef3"},
{file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:1fdc9fae8dd4c763e8a31e7630afef517eab9f5d5d31a278df087f307bf601f4"},
{file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:658f2aa69d31e09699705949b5fc4719cbecbd4a97f9656a232e7d6c7be1a367"},
{file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1473427aff3d66a3fa2199004c3e601e6c4500ab86696edffdbc84954c72d832"},
{file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a87de7dd873bf9a792bf1e58b1c3887b9264036629a5bf2d2e6579fe8e73edff"},
{file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0d7b36afa46c97875303a94e8f3ad932bf78bace9e18e603f2085b652422edcd"},
{file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:cf120cce539453ae086eacc0130a324e7026113510efa83ab42ef3fcfccac7fb"},
{file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:df5c7333167b9674aa8ae1d4008fa4bc17a313cc490b2cca27838bbdcc6bb15b"},
{file = "lxml-5.3.0-cp313-cp313-win32.whl", hash = "sha256:c802e1c2ed9f0c06a65bc4ed0189d000ada8049312cfeab6ca635e39c9608957"},
{file = "lxml-5.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:406246b96d552e0503e17a1006fd27edac678b3fcc9f1be71a2f94b4ff61528d"},
{file = "lxml-5.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7b1cd427cb0d5f7393c31b7496419da594fe600e6fdc4b105a54f82405e6626c"},
{file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51806cfe0279e06ed8500ce19479d757db42a30fd509940b1701be9c86a5ff9a"},
{file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee70d08fd60c9565ba8190f41a46a54096afa0eeb8f76bd66f2c25d3b1b83005"},
{file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:8dc2c0395bea8254d8daebc76dcf8eb3a95ec2a46fa6fae5eaccee366bfe02ce"},
{file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6ba0d3dcac281aad8a0e5b14c7ed6f9fa89c8612b47939fc94f80b16e2e9bc83"},
{file = "lxml-5.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:6e91cf736959057f7aac7adfc83481e03615a8e8dd5758aa1d95ea69e8931dba"},
{file = "lxml-5.3.0.tar.gz", hash = "sha256:4e109ca30d1edec1ac60cdbe341905dc3b8f55b16855e03a54aaf59e51ec8c6f"},
]
[[package]]
name = "markupsafe"
version = "2.1.5"
requires_python = ">=3.7"
summary = "Safely add untrusted strings to HTML/XML markup."
groups = ["default"]
files = [
{file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"},
{file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"},
{file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"},
{file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"},
{file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"},
{file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"},
{file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"},
{file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"},
{file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"},
{file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"},
{file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"},
{file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"},
{file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"},
{file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"},
{file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"},
{file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"},
{file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"},
{file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"},
{file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"},
{file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"},
{file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
{file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
{file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"},
{file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"},
{file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"},
{file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"},
{file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"},
{file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"},
{file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"},
{file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"},
{file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
]
[[package]]
name = "networkx"
version = "3.3"
requires_python = ">=3.10"
summary = "Python package for creating and manipulating graphs and networks"
groups = ["default"]
files = [
{file = "networkx-3.3-py3-none-any.whl", hash = "sha256:28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2"},
{file = "networkx-3.3.tar.gz", hash = "sha256:0c127d8b2f4865f59ae9cb8aafcd60b5c70f3241ebd66f7defad7c4ab90126c9"},
]
[[package]]
name = "packaging"
version = "24.1"
requires_python = ">=3.8"
summary = "Core utilities for Python packages"
groups = ["test"]
files = [
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
]
[[package]]
name = "persica"
version = "0.1.0a1"
requires_python = ">=3.10"
git = "https://github.com/luoshuijs/Persica"
ref = "dev"
revision = "0ef0f04a7938d7394ada2e2886a9eb70dd21c41e"
summary = "Automatic framework for Pythone"
groups = ["default"]
dependencies = [
"networkx>=3.3",
]
[[package]]
name = "platformdirs"
version = "4.3.6"
requires_python = ">=3.8"
summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
groups = ["default"]
files = [
{file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"},
{file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"},
]
[[package]]
name = "pluggy"
version = "1.5.0"
requires_python = ">=3.8"
summary = "plugin and hook calling mechanisms for python"
groups = ["test"]
files = [
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
]
[[package]]
name = "pyaes"
version = "1.6.1"
summary = "Pure-Python Implementation of the AES block-cipher and common modes of operation"
groups = ["default"]
files = [
{file = "pyaes-1.6.1.tar.gz", hash = "sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f"},
]
[[package]]
name = "pydantic"
version = "2.9.2"
requires_python = ">=3.8"
summary = "Data validation using Python type hints"
groups = ["default"]
dependencies = [
"annotated-types>=0.6.0",
"pydantic-core==2.23.4",
"typing-extensions>=4.12.2; python_version >= \"3.13\"",
"typing-extensions>=4.6.1; python_version < \"3.13\"",
]
files = [
{file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"},
{file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"},
]
[[package]]
name = "pydantic-core"
version = "2.23.4"
requires_python = ">=3.8"
summary = "Core functionality for Pydantic validation and serialization"
groups = ["default"]
dependencies = [
"typing-extensions!=4.7.0,>=4.6.0",
]
files = [
{file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"},
{file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"},
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"},
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"},
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"},
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"},
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"},
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"},
{file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"},
{file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"},
{file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"},
{file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"},
{file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"},
{file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"},
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"},
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"},
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"},
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"},
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"},
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"},
{file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"},
{file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"},
{file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"},
{file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"},
{file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"},
{file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"},
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"},
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"},
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"},
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"},
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"},
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"},
{file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"},
{file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"},
{file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"},
{file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"},
{file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"},
{file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"},
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"},
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"},
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"},
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"},
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"},
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"},
{file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"},
{file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"},
{file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"},
{file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"},
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"},
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"},
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"},
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"},
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"},
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"},
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"},
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"},
{file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"},
]
[[package]]
name = "pyreadline3"
version = "3.5.4"
requires_python = ">=3.8"
summary = "A python implementation of GNU readline."
groups = ["default"]
marker = "sys_platform == \"win32\" and python_version >= \"3.8\""
files = [
{file = "pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6"},
{file = "pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7"},
]
[[package]]
name = "pyrogram"
version = "2.0.124"
requires_python = "~=3.8"
git = "https://github.com/TeamPGM/pyrogram"
revision = "bcfc7c386bea65939775fa02f5e6d40bdccb7c7f"
summary = "Elegant, modern and asynchronous Telegram MTProto API framework in Python for users and bots"
groups = ["default"]
dependencies = [
"pyaes==1.6.1",
"pysocks==1.7.1",
]
[[package]]
name = "pyrotgcrypto"
version = "1.2.7"
requires_python = "~=3.7"
summary = "Fast and Portable Cryptography Extension Library for Pyrogram"
groups = ["default"]
files = [
{file = "PyroTgCrypto-1.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:35b2b5e5162ecea4f754412614243933536466d93c3cf3c857526d861d8c661d"},
{file = "PyroTgCrypto-1.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:991323f7c2d8c2780bd1e5342693bda6d6300205a48732b57ca865a962750fa2"},
{file = "PyroTgCrypto-1.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:38202a4672951b350afc209700b88c93f9b75d80c948dc5802f9fe80803a12db"},
{file = "PyroTgCrypto-1.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21f2ff6398036990d51a424ad630b253c455d5e57ce15a24fce1af99af4d9e1f"},
{file = "PyroTgCrypto-1.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29741048e5a54ca13094e0649d867c609feffa264f4ae76964142484f07b800f"},
{file = "PyroTgCrypto-1.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:677fc0517d6c3a94c7d90944bc77827c801af6f75a1a4a20206ceaf1db856ef2"},
{file = "PyroTgCrypto-1.2.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:64a89f1a251d9cfbbecd5255097c561f1693be54eef455c67ab43f7f5477c851"},
{file = "PyroTgCrypto-1.2.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9ddf241cfdde91b1f9dc242cddcf95d5b1ead0b446f056f650d029a38410c9da"},
{file = "PyroTgCrypto-1.2.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8b9e02dfa4ceb28a33d6d32b68d8547463713dd848f75304e06aeb9c82f9c446"},
{file = "PyroTgCrypto-1.2.7-cp310-cp310-win32.whl", hash = "sha256:61b7a1d70572795100c22129d7d848386e1890c93504dbfb54599474627cf657"},
{file = "PyroTgCrypto-1.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:dc1413f54e5f05eaa4f86525d87c78d765cbbb5f20389db46458fa4e7b429019"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8cd81935567e792a57768b3242c268cb8ccc538504c82b4d2ac2cc2e64a23a95"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fd965133558d9995635b77d461eb4c12a90b2387b9a2f4d3be0329a0cc03c66d"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d4d423d9bf1e15a1527bcfe3a3ff7aa625c7112db97635a3c2f7e9da86f19112"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e364743e762fed1006b6675f2cda117968450205a98f83c8e87b3f337d7fbf3e"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5acda6512167e2a8fdb431ec5919f1bd33b67c3a6802d69f0e7ab6b535968f9f"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72ccd78d50c3480717690f01b8e0533e591017946f02da89a954c863a9da230d"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9b6418477eb7d8d2878a873ff4352947b7c5ff8256bc8f4f714b2636f707f5f1"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0dd9b0e560a1f575bf86ab649757a7ceafd03f858d1a686398b216c5929c936"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:48542a8de389a3a5258df70708b5fdce8c63cf8a068e8cb580cd3a01689f6261"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-win32.whl", hash = "sha256:85a57a10cafafc0f95a8dd7988754f4194b281ac07e6c3e2c7c6065097f0dba9"},
{file = "PyroTgCrypto-1.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:6b58710373939a9c2c520c00666631cd782adbb14434a179d22c5eeae3f0727f"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:75dac820a0ead43bbc8f134f741472d889318d32b4f587e13342a4f412b6e6c8"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3af1a29b6c7392abb060b53dcbdbfc213253b8f891d37dc2890151356ef8ece4"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5a09deeb201de18a7e3ed2b5fca2db421ad5c610d7b6db4a9b29d63df5dae6db"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1306b9f0fbc77be8add4a6f3c68a9d1d005d1bdd970965b6936ca7419820afba"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd99a80f8c104104e30a94a25e7e8c4f190891d3aceaa9f81983358b568c2438"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca1568499a7699c399a92b84775061ce5c617ad87c1e6e1180e01caf60f47c4d"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a7f7c20bb1136afeea3e760e7e07f352787c6f9a681cdeec1b8aad18805443a"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fc384fc568f1fcdcfa3ae5b556898c9caa48f61a91ca39767cd52b420b7f1a44"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:222a5c4a243d379db075105aed4f071a377b7dad7e8c02b4055b680033a4a57b"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-win32.whl", hash = "sha256:1eda8e08a39eead928285560029957a2cf4877da3e3cb233649da073a47dc9e8"},
{file = "PyroTgCrypto-1.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:8eff5b2f18fc03b2ddcfd702d9363cb064ee56b470816a5eb2421ee7881b67f4"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:15ade101da138e520f48574e49ea7a44bab13275d019eb21feb5e9d718b6d65c"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8418ecb1a51d484de79502da4b1d7587a32599cd18ef3834f228e04370b1be3e"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a75a8c9177bcd186d37b82ce9964009c8dcf0996626cb40d743f2fa32fc61bf8"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5df7e330f0dfddbb2dae6bc9c8d0ac8acb8842383efe35590801ef247f25485c"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad37d19118656d6e6e0e7e4ff4b6f31247e892924ff1e4170c52d1db1fd22a96"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2b5ecfdd5e1609789e0ae479154661756d60c8c61beb7ed7660139f4fec1e4"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:74446fa32f9a4da4bd95903ce73553d6c9e790d480bf4a99624e56279cbeb2dc"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:96814fc33194e5c9114110197690f81b8f60bb65eb0f492d81ba3f048f7d5d9f"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c8775ebefcc3c25fa68f67126ceab6d8c38490e14249d4f80463faed2ae86612"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-win32.whl", hash = "sha256:ddcdb4ce089fe691bdca571d0a6661f6df8c1f5dbb6470e66ae43097457fcdb2"},
{file = "PyroTgCrypto-1.2.7-cp313-cp313-win_amd64.whl", hash = "sha256:bba87c07da6f76fd70ce894abc9d5321c2339aebf7968877e3726f9710f98458"},
{file = "PyroTgCrypto-1.2.7-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:021d1f1be6d49c6ff8fd351785c02bcd5e525d9e9bef6a4d3f06ce8e9e1a13eb"},
{file = "PyroTgCrypto-1.2.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f75d252d6544c88eda9f6273798d5b8d5e41fe5131b5d9accf4770e449bba59b"},
{file = "PyroTgCrypto-1.2.7-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d8211806db398ca0432824669755e547b56735eb82e26806ae60e59ebe2661c"},
{file = "PyroTgCrypto-1.2.7-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64572319f81e64d52acad145851d03aba74dbe82a32db80e8202bc938ebb395e"},
{file = "PyroTgCrypto-1.2.7-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddce8ab3709fb3cb074295187d7b8baade3bf0cf77c26683bfc9631ffcf28740"},
{file = "PyroTgCrypto-1.2.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c83f6f0a8f6c7edba2961a62dc5ffa5bcf24cd69a7f0848c287800c673797fc7"},
]
[[package]]
name = "pysocks"
version = "1.7.1"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
summary = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information."
groups = ["default"]
files = [
{file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"},
{file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"},
]
[[package]]
name = "pytest"
version = "8.3.3"
requires_python = ">=3.8"
summary = "pytest: simple powerful testing with Python"
groups = ["test"]
dependencies = [
"colorama; sys_platform == \"win32\"",
"exceptiongroup>=1.0.0rc8; python_version < \"3.11\"",
"iniconfig",
"packaging",
"pluggy<2,>=1.5",
"tomli>=1; python_version < \"3.11\"",
]
files = [
{file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"},
{file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"},
]
[[package]]
name = "pytest-asyncio"
version = "0.24.0"
requires_python = ">=3.8"
summary = "Pytest support for asyncio"
groups = ["test"]
dependencies = [
"pytest<9,>=8.2",
]
files = [
{file = "pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b"},
{file = "pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276"},
]
[[package]]
name = "python-dotenv"
version = "1.0.1"
requires_python = ">=3.8"
summary = "Read key-value pairs from a .env file and set them as environment variables"
groups = ["default"]
files = [
{file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
{file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
]
[[package]]
name = "pytz"
version = "2024.2"
summary = "World timezone definitions, modern and historical"
groups = ["default"]
files = [
{file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"},
{file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"},
]
[[package]]
name = "six"
version = "1.16.0"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
summary = "Python 2 and 3 compatibility utilities"
groups = ["default"]
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]]
name = "sniffio"
version = "1.3.1"
requires_python = ">=3.7"
summary = "Sniff out which async library your code is running under"
groups = ["default"]
files = [
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
]
[[package]]
name = "soupsieve"
version = "2.6"
requires_python = ">=3.8"
summary = "A modern CSS selector implementation for Beautiful Soup."
groups = ["default"]
files = [
{file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"},
{file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"},
]
[[package]]
name = "starlette"
version = "0.38.5"
requires_python = ">=3.8"
summary = "The little ASGI library that shines."
groups = ["default"]
dependencies = [
"anyio<5,>=3.4.0",
"typing-extensions>=3.10.0; python_version < \"3.10\"",
]
files = [
{file = "starlette-0.38.5-py3-none-any.whl", hash = "sha256:632f420a9d13e3ee2a6f18f437b0a9f1faecb0bc42e1942aa2ea0e379a4c4206"},
{file = "starlette-0.38.5.tar.gz", hash = "sha256:04a92830a9b6eb1442c766199d62260c3d4dc9c4f9188360626b1e0273cb7077"},
]
[[package]]
name = "tomli"
version = "2.0.1"
requires_python = ">=3.7"
summary = "A lil' TOML parser"
groups = ["test"]
marker = "python_version < \"3.11\""
files = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
[[package]]
name = "typing-extensions"
version = "4.12.2"
requires_python = ">=3.8"
summary = "Backported and Experimental Type Hints for Python 3.8+"
groups = ["default"]
files = [
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
[[package]]
name = "tzdata"
version = "2024.1"
requires_python = ">=2"
summary = "Provider of IANA time zone data"
groups = ["default"]
marker = "platform_system == \"Windows\""
files = [
{file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"},
{file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"},
]
[[package]]
name = "tzlocal"
version = "5.2"
requires_python = ">=3.8"
summary = "tzinfo object for the local timezone"
groups = ["default"]
dependencies = [
"backports-zoneinfo; python_version < \"3.9\"",
"tzdata; platform_system == \"Windows\"",
]
files = [
{file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"},
{file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"},
]
[[package]]
name = "uritools"
version = "4.0.3"
requires_python = ">=3.7"
summary = "URI parsing, classification and composition"
groups = ["default"]
files = [
{file = "uritools-4.0.3-py3-none-any.whl", hash = "sha256:bae297d090e69a0451130ffba6f2f1c9477244aa0a5543d66aed2d9f77d0dd9c"},
{file = "uritools-4.0.3.tar.gz", hash = "sha256:ee06a182a9c849464ce9d5fa917539aacc8edd2a4924d1b7aabeeecabcae3bc2"},
]
[[package]]
name = "urlextract"
version = "1.9.0"
summary = "Collects and extracts URLs from given text."
groups = ["default"]
dependencies = [
"filelock",
"idna",
"platformdirs",
"uritools",
]
files = [
{file = "urlextract-1.9.0-py3-none-any.whl", hash = "sha256:f88963532488b1c7c405e21bd162ae97871754ea04b60e18d33ee075b19b82fd"},
{file = "urlextract-1.9.0.tar.gz", hash = "sha256:70508e02ba9df372e25cf0642db367cece273e8712cd0ce78178fc5dd7ea00db"},
]
[[package]]
name = "uvicorn"
version = "0.30.6"
requires_python = ">=3.8"
summary = "The lightning-fast ASGI server."
groups = ["default"]
dependencies = [
"click>=7.0",
"h11>=0.8",
"typing-extensions>=4.0; python_version < \"3.11\"",
]
files = [
{file = "uvicorn-0.30.6-py3-none-any.whl", hash = "sha256:65fd46fe3fda5bdc1b03b94eb634923ff18cd35b2f084813ea79d1f103f711b5"},
{file = "uvicorn-0.30.6.tar.gz", hash = "sha256:4b15decdda1e72be08209e860a1e10e92439ad5b97cf44cc945fcbee66fc5788"},
]

38
pyproject.toml Normal file
View File

@ -0,0 +1,38 @@
[project]
name = "FixMiYouShe"
version = "0.1.0"
description = "Default template for PDM package"
authors = [
{name = "xtaodada", email = "xtao@xtaolink.cn"},
]
dependencies = [
"httpx>=0.24.1",
"fastapi>=0.110.0",
"starlette",
"uvicorn>=0.23.2",
"pydantic",
"python-dotenv",
"coloredlogs",
"pytz",
"apscheduler",
"aiofiles>=23.2.1",
"jinja2>=3.1.3",
"beautifulsoup4",
"lxml",
"PyroTgCrypto>=1.2.7",
"pyrogram @ git+https://github.com/TeamPGM/pyrogram",
"urlextract",
"persica @ git+https://github.com/luoshuijs/Persica@dev",
]
requires-python = ">=3.10"
readme = "README.md"
license = {text = "AGPL 3.0+"}
[tool.pdm]
distribution = false
[tool.pdm.dev-dependencies]
test = [
"pytest>=8.3.3",
"pytest-asyncio>=0.24.0",
]

View File

@ -1,16 +1,51 @@
httpx==0.24.1
fastapi~=0.110.0
starlette
uvicorn~=0.23.2
pydantic
python-dotenv
coloredlogs
pytz
apscheduler
aiofiles==23.2.1
jinja2==3.1.3
beautifulsoup4
lxml
PyroTgCrypto==1.2.6a0
git+https://github.com/TeamPGM/pyrogram
urlextract
# This file is @generated by PDM.
# Please do not edit it manually.
aiofiles==24.1.0
annotated-types==0.7.0
anyio==4.5.0
apscheduler==3.10.4
beautifulsoup4==4.12.3
certifi==2024.8.30
click==8.1.7
colorama==0.4.6; sys_platform == "win32" or platform_system == "Windows"
coloredlogs==15.0.1
exceptiongroup==1.2.2; python_version < "3.11"
fastapi==0.115.0
filelock==3.16.1
h11==0.14.0
httpcore==1.0.5
httpx==0.27.2
humanfriendly==10.0
idna==3.10
iniconfig==2.0.0
jinja2==3.1.4
lxml==5.3.0
markupsafe==2.1.5
networkx==3.3
packaging==24.1
persica @ git+https://github.com/luoshuijs/Persica@dev
platformdirs==4.3.6
pluggy==1.5.0
pyaes==1.6.1
pydantic==2.9.2
pydantic-core==2.23.4
pyreadline3==3.5.4; sys_platform == "win32" and python_version >= "3.8"
pyrogram @ git+https://github.com/TeamPGM/pyrogram
pyrotgcrypto==1.2.7
pysocks==1.7.1
pytest==8.3.3
pytest-asyncio==0.24.0
python-dotenv==1.0.1
pytz==2024.2
six==1.16.0
sniffio==1.3.1
soupsieve==2.6
starlette==0.38.5
tomli==2.0.1; python_version < "3.11"
typing-extensions==4.12.2
tzdata==2024.1; platform_system == "Windows"
tzlocal==5.2
uritools==4.0.3
urlextract==1.9.0
uvicorn==0.30.6

View File

@ -1,17 +0,0 @@
from pyrogram import Client
from pathlib import Path
from .env import BOT_API_ID_INT, BOT_API_HASH, BOT_TOKEN
data_path = Path("data")
data_path.mkdir(exist_ok=True)
bot = Client(
"bot",
api_id=int(BOT_API_ID_INT),
api_hash=BOT_API_HASH,
bot_token=BOT_TOKEN,
workdir="data",
plugins=dict(root="src/plugins"),
)

34
src/core/bot.py Normal file
View File

@ -0,0 +1,34 @@
from persica.factory.component import AsyncInitializingComponent
from pyrogram import Client
from pathlib import Path
from src.env import BOT, BOT_API_ID_INT, BOT_API_HASH, BOT_TOKEN
data_path = Path("data")
data_path.mkdir(exist_ok=True)
class TelegramBot(AsyncInitializingComponent):
def __init__(self):
self.bot = Client(
"bot",
api_id=int(BOT_API_ID_INT),
api_hash=BOT_API_HASH,
bot_token=BOT_TOKEN,
workdir="data",
)
async def initialize(self):
if not BOT:
return
await self.bot.start()
async def shutdown(self):
if not BOT:
return
try:
await self.bot.stop()
except RuntimeError:
pass

13
src/core/scheduler.py Normal file
View File

@ -0,0 +1,13 @@
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from fastapi import FastAPI
from persica.factory.component import BaseComponent
class TimeScheduler(BaseComponent):
def __init__(self):
self.scheduler = AsyncIOScheduler(timezone="Asia/ShangHai")
def register_scheduler(self, app: "FastAPI"):
@app.on_event("startup")
async def start_event():
self.scheduler.start()

View File

@ -3,39 +3,33 @@ import asyncio
import uvicorn
from fastapi import FastAPI
from persica.factory.component import AsyncInitializingComponent
from starlette.middleware.trustedhost import TrustedHostMiddleware
from .env import DOMAIN, DEBUG, PORT
from .route import get_routes
from .route.base import UserAgentMiddleware
from .services.scheduler import register_scheduler
app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
from src.core.scheduler import TimeScheduler
from src.env import DOMAIN, DEBUG, PORT
class Web:
def __init__(self):
class WebApp(AsyncInitializingComponent):
def __init__(self, scheduler: TimeScheduler):
self.app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
scheduler.register_scheduler(self.app)
self.web_server = None
self.web_server_task = None
self.bot_main_task = None
@staticmethod
def init_web():
def init_web(self):
if not DEBUG:
app.add_middleware(
self.app.add_middleware(
TrustedHostMiddleware,
allowed_hosts=[
DOMAIN,
],
)
app.add_middleware(UserAgentMiddleware)
get_routes()
register_scheduler(app)
async def start(self):
self.init_web()
self.web_server = uvicorn.Server(
config=uvicorn.Config(app, host="0.0.0.0", port=PORT)
config=uvicorn.Config(self.app, host="0.0.0.0", port=PORT)
)
server_config = self.web_server.config
server_config.setup_event_loop()
@ -54,8 +48,14 @@ class Web:
def stop(self):
if self.web_server_task:
self.web_server_task.cancel()
if self.bot_main_task:
self.bot_main_task.cancel()
async def initialize(self):
await self.start()
web = Web()
async def shutdown(self):
self.stop()
if self.web_server:
try:
await self.web_server.shutdown()
except AttributeError:
pass

View File

@ -2,16 +2,16 @@
"game_list": [
{
"id": "2",
"icon": "https://fastcdn.hoyoverse.com/static-resource-v2/2023/11/08/9db76fb146f82c045bc276956f86e047_6878380451593228482.png",
"bg": "https://upload-os-bbs.hoyolab.com/upload/2024/07/11/af3fa25fb0cac1959da97b6b867fdb57_6289156149732603194.jpg?x-oss-process=image/auto-orient,0/interlace,1/format,webp/quality,q_70",
"icon": "https://fastcdn.hoyoverse.com/static-resource-v2/2024/08/28/477df7dc8ccb9343da4aea31091c4723_802231292277516724.png",
"bg": "https://upload-os-bbs.hoyolab.com/upload/2024/08/22/2c103142df58ff983fcd3bc47d397c49_3439523162404792698.png?x-oss-process=image/auto-orient,0/interlace,1/format,webp/quality,q_70",
"name": "原神",
"bg_color": "#244C74",
"bg_color": "#6E2C14",
"focus_channel_id": "30"
},
{
"id": "6",
"icon": "https://hyl-static-res-prod.hoyolab.com/communityweb/business/starrail_hoyoverse.png",
"bg": "https://upload-os-bbs.hoyolab.com/upload/2024/07/31/8981eebc4cd223331a0eedaca9b73f19_928166619611008481.jpg?x-oss-process=image/auto-orient,0/interlace,1/format,webp/quality,q_70",
"bg": "https://upload-os-bbs.hoyolab.com/upload/2024/09/10/a2e1dbea2d1b7af095941428eb233f95_5829553462118520641.jpg?x-oss-process=image/auto-orient,0/interlace,1/format,webp/quality,q_70",
"name": "崩坏:星穹铁道",
"bg_color": "#101521",
"focus_channel_id": "42"
@ -19,7 +19,7 @@
{
"id": "8",
"icon": "https://hyl-static-res-prod.hoyolab.com/communityweb/business/nap.png",
"bg": "https://upload-os-bbs.hoyolab.com/upload/2024/06/28/1f817e30accd6c117aba10760c52552f_1609948843932447239.jpg?x-oss-process=image/auto-orient,0/interlace,1/format,webp/quality,q_70",
"bg": "https://upload-os-bbs.hoyolab.com/upload/2024/08/13/d0ebd742d2afe541118c14d2d863118e_7814679909409111693.jpg?x-oss-process=image/auto-orient,0/interlace,1/format,webp/quality,q_70",
"name": "绝区零",
"bg_color": "#F5F6FB",
"focus_channel_id": "46"
@ -27,9 +27,9 @@
{
"id": "1",
"icon": "https://fastcdn.hoyoverse.com/static-resource-v2/2024/02/29/3d96534fd7a35a725f7884e6137346d1_3942255444511793944.png",
"bg": "https://upload-os-bbs.hoyolab.com/upload/2024/07/24/c6e8a685963be61470df222b71e28a3f_2653988210193011390.jpg?x-oss-process=image/auto-orient,0/interlace,1/format,webp/quality,q_70",
"bg": "https://upload-os-bbs.hoyolab.com/upload/2024/09/02/ef9669e2ec4f331407d265aa5d5eb4c1_7138618278434371705.jpg?x-oss-process=image/auto-orient,0/interlace,1/format,webp/quality,q_70",
"name": "Honkai Impact 3rd",
"bg_color": "#581312",
"bg_color": "#292180",
"focus_channel_id": "0"
},
{
@ -42,7 +42,7 @@
},
{
"id": "5",
"icon": "https://webstatic.hoyoverse.com/upload/static-resource/2022/08/04/8a31e3d6bce7684556cd45b1e1c309bf_1216320235452608527.png",
"icon": "https://hyl-static-res-prod.hoyolab.com/communityWeb/pgc/business/hyl_icon.png",
"bg": "https://upload-os-bbs.hoyolab.com/upload/2024/08/09/1e4a3ac09f82fd7f7702c3ec19dc38fd_7412144515818250508.jpg?x-oss-process=image/auto-orient,0/interlace,1/format,webp/quality,q_70",
"name": "HoYoLAB",
"bg_color": "#61C1F2",

View File

@ -1,5 +1,7 @@
from typing import List, Optional
from persica.factory.component import BaseComponent
from pyrogram import Client
from pyrogram.types import (
InputTextMessageContent,
InlineQueryResultArticle,
@ -9,14 +11,14 @@ from pyrogram.types import (
InlineQueryResultDocument,
)
from src.core.bot import TelegramBot
from .start import get_test_button
from ..api.bot_request import get_post_info
from ..api.models import PostInfo
from ..bot import bot
from ..utils.url import get_lab_link
def get_help_article() -> InlineQueryResultArticle:
def get_help_article(bot: Client) -> InlineQueryResultArticle:
text = f"欢迎使用 @{bot.me.username} 来转换 米游社/HoYoLab 链接,您也可以将 Bot 添加到群组或频道自动匹配消息。"
return InlineQueryResultArticle(
title=">> 帮助 <<",
@ -72,10 +74,9 @@ async def add_document_results(
return result
@bot.on_inline_query()
async def inline(_, query: InlineQuery):
async def inline(bot: Client, query: InlineQuery):
message = query.query
results = [get_help_article()]
results = [get_help_article(bot)]
if message:
replace_list = get_lab_link(message)
if replace_list:
@ -98,3 +99,10 @@ async def inline(_, query: InlineQuery):
switch_pm_parameter="start",
results=results,
)
class InlineBotPlugin(BaseComponent):
def __init__(self, telegram_bot: TelegramBot):
@telegram_bot.bot.on_inline_query()
async def inline_query(_, query: InlineQuery):
await inline(_, query)

View File

@ -1,11 +1,12 @@
from asyncio import sleep
from persica.factory.component import BaseComponent
from pyrogram import filters
from pyrogram.enums import MessageEntityType, ChatType
from pyrogram.errors import WebpageNotFound
from pyrogram.types import Message, MessageEntity
from src.bot import bot
from src.core.bot import TelegramBot
from src.log import logger
from src.utils.url import get_lab_link
@ -80,15 +81,6 @@ async def process_link_func(markdown_text: str, message: Message):
await sleep(0.5)
@bot.on_message(
filters=filters.incoming
& ~filters.via_bot
& need_text
& need_chat
& ~forward_from_bot
& ~forward_in_group,
group=1,
)
async def process_link(_, message: Message):
text = message.text or message.caption
markdown_text = text.markdown
@ -99,13 +91,6 @@ async def process_link(_, message: Message):
await process_link_func(markdown_text, message)
@bot.on_message(
filters=filters.incoming
& filters.command("parse")
& ~filters.forwarded
& ~filters.via_bot
& need_chat,
)
async def parse_reply_link(_, message: Message):
reply = message.reply_to_message
if not reply:
@ -117,3 +102,28 @@ async def parse_reply_link(_, message: Message):
if not markdown_text:
return
await process_link_func(markdown_text, reply)
class MessageBotPlugin(BaseComponent):
def __init__(self, telegram_bot: TelegramBot):
@telegram_bot.bot.on_message(
filters=filters.incoming
& ~filters.via_bot
& need_text
& need_chat
& ~forward_from_bot
& ~forward_in_group,
group=1,
)
async def _process_link(_, message: Message):
await process_link(_, message)
@telegram_bot.bot.on_message(
filters=filters.incoming
& filters.command("parse")
& ~filters.forwarded
& ~filters.via_bot
& need_chat,
)
async def _parse_reply_link(_, message: Message):
await parse_reply_link(_, message)

View File

@ -1,12 +1,12 @@
import contextlib
from datetime import datetime, timedelta
from asyncio import sleep
from persica.factory.component import BaseComponent
from pyrogram import filters
from pyrogram.enums import ChatType
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message
from src.bot import bot
from src.services.scheduler import scheduler
from src.core.bot import TelegramBot
HELP_MSG = "此 BOT 将会自动回复可以转换成 Telegram 预览的 URL 链接,可以提供更直观、方便的浏览体验。"
TEST_URL = "https://m.miyoushe.com/ys?channel=xiaomi/#/article/51867765"
@ -25,21 +25,6 @@ def get_test_button() -> InlineKeyboardMarkup:
)
async def delete_message(message: Message):
with contextlib.suppress(Exception):
await message.delete()
def add_delete_message_task(message: Message):
scheduler.add_job(
delete_message,
"date",
run_date=datetime.now() + timedelta(seconds=60),
args=(message,),
)
@bot.on_message(filters=filters.command("start"))
async def start(_, message: "Message"):
reply = await message.reply_text(
HELP_MSG,
@ -47,4 +32,13 @@ async def start(_, message: "Message"):
reply_markup=get_test_button(),
)
if message.chat and message.chat.type in [ChatType.GROUP, ChatType.SUPERGROUP]:
add_delete_message_task(reply)
await sleep(30)
with contextlib.suppress(Exception):
await reply.delete()
class StartBotPlugin(BaseComponent):
def __init__(self, telegram_bot: TelegramBot):
@telegram_bot.bot.on_message(filters=filters.command("start"))
async def _start(_, message: "Message"):
await start(_, message)

View File

@ -18,10 +18,9 @@ from src.api.models import (
clean_url,
)
from src.data.get_bg import BG_MAP
from src.env import DOMAIN, MIYOUSHE
from src.env import DOMAIN
from src.error import ArticleNotFoundError
from src.log import logger
from src.services.scheduler import scheduler
RECOMMEND_POST_MAP: Dict[str, List[PostRecommend]] = {}
template = template_env.get_template("article.jinja2")
@ -227,16 +226,13 @@ async def process_article(game_id: str, post_id: int, i18n: I18n = I18n()) -> st
return content # noqa
if MIYOUSHE:
@scheduler.scheduled_job("cron", minute="0", second="10")
async def refresh_recommend_posts():
async def refresh_recommend_posts():
logger.info("Start to refresh recommend posts")
async with Hyperion() as hyperion:
for key, gids in GAME_ID_MAP.items():
try:
RECOMMEND_POST_MAP[key] = (
await hyperion.get_official_recommended_posts(gids)
RECOMMEND_POST_MAP[key] = await hyperion.get_official_recommended_posts(
gids
)
except Exception as _:
logger.exception(f"Failed to get recommend posts gids={gids}")

View File

@ -4,7 +4,6 @@ from typing import Dict, List, Callable
from src.api.hoyolab import Hoyolab
from src.api.i18n import I18n, i18n_alias
from src.api.models import PostRecommend, PostType, PostInfo
from src.env import HOYOLAB
from src.log import logger
from src.render.article import (
process_article_text,
@ -12,7 +11,6 @@ from src.render.article import (
template,
get_public_data,
)
from src.services.scheduler import scheduler
GAME_ID_MAP = {"bh3": 1, "ys": 2, "wd": 4, "dby": 5, "sr": 6, "zzz": 8}
RECOMMEND_POST_MAP: Dict[int, List[PostRecommend]] = {}
@ -75,10 +73,7 @@ async def process_article(post_id: int, lang: str) -> str:
return content # noqa
if HOYOLAB:
@scheduler.scheduled_job("cron", minute="0", second="10")
async def refresh_hoyo_recommend_posts():
async def refresh_hoyo_recommend_posts():
logger.info("Start to refresh hoyolab recommend posts")
async with Hoyolab() as hoyolab:
for gids in GAME_ID_MAP.values():

View File

@ -1,18 +0,0 @@
from src.env import MIYOUSHE, HOYOLAB
def get_routes():
from .error import validation_exception_handler
routes = [
validation_exception_handler,
]
if MIYOUSHE:
from .article import parse_article
routes.append(parse_article)
if HOYOLAB:
from .article_hoyolab import parse_hoyo_article
routes.append(parse_hoyo_article)

View File

@ -1,15 +1,34 @@
from persica.factory.component import AsyncInitializingComponent
from starlette.requests import Request
from starlette.responses import HTMLResponse
from .base import get_redirect_response
from ..app import app
from ..error import ArticleError, ResponseException
from ..log import logger
from ..render.article import process_article, get_post_info
from src.core.web_app import WebApp
from src.core.scheduler import TimeScheduler
from src.env import MIYOUSHE
from src.error import ArticleError, ResponseException
from src.log import logger
from src.render.article import process_article, get_post_info, refresh_recommend_posts
@app.get("/{game_id}/article/{post_id}")
async def parse_article(game_id: str, post_id: int, request: Request):
class ArticlePlugin(AsyncInitializingComponent):
def __init__(self, web_app: WebApp, sche: TimeScheduler):
if not MIYOUSHE:
return
web_app.app.add_api_route("/{game_id}/article/{post_id}", self.parse_article)
web_app.app.add_api_route(
"/{game_id}/article/{post_id}/json", self.parse_article_json
)
sche.scheduler.add_job(refresh_recommend_posts, "cron", minute="0", second="10")
async def initialize(self):
if not MIYOUSHE:
return
await refresh_recommend_posts()
@staticmethod
async def parse_article(game_id: str, post_id: int, request: Request):
try:
return HTMLResponse(await process_article(game_id, post_id))
except ResponseException as e:
@ -24,9 +43,8 @@ async def parse_article(game_id: str, post_id: int, request: Request):
)
return get_redirect_response(request)
@app.get("/{game_id}/article/{post_id}/json")
async def parse_article_json(game_id: str, post_id: int, request: Request):
@staticmethod
async def parse_article_json(game_id: str, post_id: int, request: Request):
try:
return await get_post_info(game_id, post_id)
except ArticleError as e:

View File

@ -1,16 +1,38 @@
from persica.factory.component import AsyncInitializingComponent
from starlette.requests import Request
from starlette.responses import HTMLResponse
from .base import get_redirect_response
from ..app import app
from ..error import ArticleError, ResponseException
from ..log import logger
from ..render.article_hoyolab import process_article, get_post_info
from src.core.web_app import WebApp
from src.core.scheduler import TimeScheduler
from src.env import HOYOLAB
from src.error import ArticleError, ResponseException
from src.log import logger
from src.render.article_hoyolab import (
process_article,
get_post_info,
refresh_hoyo_recommend_posts,
)
@app.get("/article/{post_id}")
@app.get("/article/{post_id}/{lang}")
async def parse_hoyo_article(post_id: int, request: Request, lang: str = "zh-cn"):
class ArticleHoYoPlugin(AsyncInitializingComponent):
def __init__(self, web_app: WebApp, sche: TimeScheduler):
if not HOYOLAB:
return
web_app.app.add_api_route("/article/{post_id}", self.parse_hoyo_article)
web_app.app.add_api_route("/article/{post_id}/{lang}", self.parse_hoyo_article)
sche.scheduler.add_job(
refresh_hoyo_recommend_posts, "cron", minute="0", second="20"
)
async def initialize(self):
if not HOYOLAB:
return
await refresh_hoyo_recommend_posts()
@staticmethod
async def parse_hoyo_article(post_id: int, request: Request, lang: str = "zh-cn"):
try:
if lang == "json":
return await get_post_info(post_id, "zh-cn")

View File

@ -1,9 +1,11 @@
from typing import TYPE_CHECKING
from persica.factory.component import BaseComponent
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import RedirectResponse
from src.env import MIYOUSHE
from src.core.web_app import WebApp
from src.env import MIYOUSHE, DEBUG
if TYPE_CHECKING:
from starlette.middleware.base import RequestResponseEndpoint
@ -26,3 +28,9 @@ class UserAgentMiddleware(BaseHTTPMiddleware):
if (not user_agent) or ("telegram" not in user_agent.lower()):
return get_redirect_response(request)
return await call_next(request)
class BaseRoutePlugin(BaseComponent):
def __init__(self, web_app: WebApp):
if not DEBUG:
web_app.app.add_middleware(UserAgentMiddleware)

View File

@ -1,11 +1,18 @@
from fastapi.exceptions import RequestValidationError
from persica.factory.component import BaseComponent
from starlette.requests import Request
from src.app import app
from src.core.web_app import WebApp
from src.route.base import get_redirect_response
@app.exception_handler(RequestValidationError)
@app.exception_handler(404)
async def validation_exception_handler(request: "Request", _):
class ErrorRoutePlugin(BaseComponent):
def __init__(self, web_app: WebApp):
web_app.app.add_exception_handler(
RequestValidationError, self.validation_exception_handler
)
web_app.app.add_exception_handler(404, self.validation_exception_handler)
@staticmethod
async def validation_exception_handler(request: "Request", _):
return get_redirect_response(request)

View File

@ -1,10 +0,0 @@
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from fastapi import FastAPI
scheduler = AsyncIOScheduler(timezone="Asia/ShangHai")
def register_scheduler(app: "FastAPI"):
@app.on_event("startup")
async def start_event():
scheduler.start()

0
tests/__init__.py Normal file
View File