diff --git a/.gitignore b/.gitignore index f6e71ae..077eacc 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,14 @@ Untitled* *_cache* *backup* *.pyc +node_modules +.prettier* +package.json +pnpm-lock.yaml +*.drawio.svg +package-lock.json +*Zone.Identifier +.env* +bot.py +TODO +*.fish diff --git a/nonebot_plugin_tetris_stats/__init__.py b/nonebot_plugin_tetris_stats/__init__.py index dab363f..3f08ae5 100644 --- a/nonebot_plugin_tetris_stats/__init__.py +++ b/nonebot_plugin_tetris_stats/__init__.py @@ -20,3 +20,4 @@ __plugin_meta__ = PluginMetadata( ) from . import game_data_processor # noqa: F401, E402 +from .utils import host # noqa: F401, E402 diff --git a/nonebot_plugin_tetris_stats/db/__init__.py b/nonebot_plugin_tetris_stats/db/__init__.py index 642216e..84d4202 100644 --- a/nonebot_plugin_tetris_stats/db/__init__.py +++ b/nonebot_plugin_tetris_stats/db/__init__.py @@ -1,3 +1,5 @@ +from enum import StrEnum, auto + from nonebot_plugin_orm import AsyncSession from sqlalchemy import select @@ -5,6 +7,11 @@ from ..utils.typing import GameType from .models import Bind +class BindStatus(StrEnum): + SUCCESS = auto() + UPDATE = auto() + + async def query_bind_info( session: AsyncSession, chat_platform: str, @@ -27,7 +34,7 @@ async def create_or_update_bind( chat_account: str, game_platform: GameType, game_account: str, -) -> str: +) -> BindStatus: bind = await query_bind_info( session=session, chat_platform=chat_platform, @@ -42,9 +49,9 @@ async def create_or_update_bind( game_account=game_account, ) session.add(bind) - message = '绑定成功' + message = BindStatus.SUCCESS else: bind.game_account = game_account - message = '更新绑定成功' + message = BindStatus.UPDATE await session.commit() return message diff --git a/nonebot_plugin_tetris_stats/game_data_processor/__init__.py b/nonebot_plugin_tetris_stats/game_data_processor/__init__.py index 2146c3c..31b98fb 100644 --- a/nonebot_plugin_tetris_stats/game_data_processor/__init__.py +++ b/nonebot_plugin_tetris_stats/game_data_processor/__init__.py @@ -4,6 +4,8 @@ from typing import Any from nonebot.matcher import Matcher from nonebot_plugin_alconna import AlcMatches, AlconnaMatcher +from nonebot_plugin_alconna.uniseg import UniMessage +from nonebot_plugin_userinfo import UserInfo # type: ignore[import-untyped] from ..utils.exception import MessageFormatError from ..utils.recorder import Recorder @@ -41,7 +43,14 @@ class Processor(ABC): raise NotImplementedError @abstractmethod - async def handle_bind(self, platform: str, account: str) -> str: + async def handle_bind( + self, + platform: str, + account: str, + bot_info: UserInfo, + *args: Any, # noqa: ANN401 + **kwargs: Any, # noqa: ANN401 + ) -> UniMessage: """处理绑定消息""" raise NotImplementedError diff --git a/nonebot_plugin_tetris_stats/game_data_processor/io_data_processor/__init__.py b/nonebot_plugin_tetris_stats/game_data_processor/io_data_processor/__init__.py index c99ca30..8a801cc 100644 --- a/nonebot_plugin_tetris_stats/game_data_processor/io_data_processor/__init__.py +++ b/nonebot_plugin_tetris_stats/game_data_processor/io_data_processor/__init__.py @@ -6,6 +6,7 @@ from nonebot.adapters import Bot, Event from nonebot.matcher import Matcher from nonebot_plugin_alconna import At, on_alconna from nonebot_plugin_orm import get_session +from nonebot_plugin_userinfo import BotUserInfo, UserInfo # type: ignore[import-untyped] from sqlalchemy import func, select from ...db import query_bind_info @@ -86,17 +87,16 @@ alc.shortcut('fkosk', {'command': 'io查', 'args': ['我']}) @alc.assign('bind') -async def _(bot: Bot, event: Event, matcher: Matcher, account: User): - proc = Processor( - event_id=id(event), - user=account, - command_args=[], - ) +async def _(bot: Bot, event: Event, matcher: Matcher, account: User, bot_info: UserInfo = BotUserInfo()): # noqa: B008 + proc = Processor(event_id=id(event), user=account, command_args=[]) try: - await matcher.finish(await proc.handle_bind(platform=get_platform(bot), account=event.get_user_id())) + await ( + await proc.handle_bind(platform=get_platform(bot), account=event.get_user_id(), bot_info=bot_info) + ).send() except NeedCatchError as e: await matcher.send(str(e)) raise HandleNotFinishedError from e + await matcher.finish() @alc.assign('query') diff --git a/nonebot_plugin_tetris_stats/game_data_processor/io_data_processor/processor.py b/nonebot_plugin_tetris_stats/game_data_processor/io_data_processor/processor.py index 41da82d..8be1c6a 100644 --- a/nonebot_plugin_tetris_stats/game_data_processor/io_data_processor/processor.py +++ b/nonebot_plugin_tetris_stats/game_data_processor/io_data_processor/processor.py @@ -1,26 +1,33 @@ from collections import defaultdict from collections.abc import Callable from datetime import datetime, timedelta, timezone -from hashlib import sha512 +from hashlib import md5, sha512 from math import floor from re import match from statistics import mean from typing import Literal +from urllib.parse import urlunparse from aiofiles import open from nonebot import get_driver from nonebot.compat import type_validate_json from nonebot.utils import run_sync +from nonebot_plugin_alconna.uniseg import UniMessage from nonebot_plugin_apscheduler import scheduler # type: ignore[import-untyped] from nonebot_plugin_localstore import get_data_file # type: ignore[import-untyped] from nonebot_plugin_orm import get_session +from nonebot_plugin_userinfo import UserInfo as NBUserInfo # type: ignore[import-untyped] from sqlalchemy import select from zstandard import ZstdCompressor -from ...db import create_or_update_bind +from ...db import BindStatus, create_or_update_bind +from ...utils.avatar import get_avatar from ...utils.exception import MessageFormatError, RequestError, WhatTheFuckError +from ...utils.host import HostPage, get_self_netloc +from ...utils.render import render from ...utils.request import splice_url from ...utils.retry import retry +from ...utils.screenshot import screenshot from .. import Processor as ProcessorMeta from .cache import Cache from .constant import BASE_URL, GAME_TYPE, RANK_PERCENTILE @@ -65,20 +72,43 @@ class Processor(ProcessorMeta): def game_platform(self) -> Literal['IO']: return GAME_TYPE - async def handle_bind(self, platform: str, account: str) -> str: + async def handle_bind(self, platform: str, account: str, bot_info: NBUserInfo) -> UniMessage: """处理绑定消息""" self.command_type = 'bind' await self.get_user() if self.user.ID is None: raise # FIXME: 不知道怎么才能把这类型给变过来了 async with get_session() as session: - return await create_or_update_bind( + bind_status = await create_or_update_bind( session=session, chat_platform=platform, chat_account=account, game_platform=GAME_TYPE, game_account=self.user.ID, ) + bot_avatar = await get_avatar(bot_info, 'Data URI', '../../static/logo/logo.svg') + user_info = await self.get_user_info() + if bind_status in (BindStatus.SUCCESS, BindStatus.UPDATE): + async with HostPage( + await render( + 'bind.j2.html', + user_avatar=f'https://tetr.io/user-content/avatars/{user_info.data.user.id}.jpg?rv={user_info.data.user.avatar_revision}' + if user_info.data.user.avatar_revision is not None + else f'../../identicon?md5={md5(user_info.data.user.id.encode()).hexdigest()}', # noqa: S324 + state='unknown', + bot_avatar=bot_avatar, + game_type=self.game_platform, + user_name=user_info.data.user.username.upper(), + bot_name=bot_info.user_name, + command='io查我', + ) + ) as page_hash: + message = UniMessage.image( + raw=await screenshot( + urlunparse(('http', get_self_netloc(), f'/host/page/{page_hash}.html', '', '', '')) + ) + ) + return message async def handle_query(self) -> str: """处理查询消息""" diff --git a/nonebot_plugin_tetris_stats/game_data_processor/top_data_processor/__init__.py b/nonebot_plugin_tetris_stats/game_data_processor/top_data_processor/__init__.py index d11f6b3..8b15483 100644 --- a/nonebot_plugin_tetris_stats/game_data_processor/top_data_processor/__init__.py +++ b/nonebot_plugin_tetris_stats/game_data_processor/top_data_processor/__init__.py @@ -3,6 +3,7 @@ from nonebot.adapters import Bot, Event from nonebot.matcher import Matcher from nonebot_plugin_alconna import At, on_alconna from nonebot_plugin_orm import get_session +from nonebot_plugin_userinfo import BotUserInfo, EventUserInfo, UserInfo # type: ignore[import-untyped] from ...db import query_bind_info from ...utils.exception import HandleNotFinishedError, NeedCatchError @@ -67,17 +68,29 @@ alc = on_alconna( @alc.assign('bind') -async def _(bot: Bot, event: Event, matcher: Matcher, account: User): +async def _( # noqa: PLR0913 + bot: Bot, + event: Event, + matcher: Matcher, + account: User, + bot_info: UserInfo = BotUserInfo(), # noqa: B008 + user_info: UserInfo = EventUserInfo(), # noqa: B008 +): proc = Processor( event_id=id(event), user=account, command_args=[], ) try: - await matcher.finish(await proc.handle_bind(platform=get_platform(bot), account=event.get_user_id())) + await ( + await proc.handle_bind( + platform=get_platform(bot), account=event.get_user_id(), bot_info=bot_info, user_info=user_info + ) + ).send() except NeedCatchError as e: await matcher.send(str(e)) raise HandleNotFinishedError from e + await matcher.finish() @alc.assign('query') diff --git a/nonebot_plugin_tetris_stats/game_data_processor/top_data_processor/processor.py b/nonebot_plugin_tetris_stats/game_data_processor/top_data_processor/processor.py index ae0d2a6..2c3c1b8 100644 --- a/nonebot_plugin_tetris_stats/game_data_processor/top_data_processor/processor.py +++ b/nonebot_plugin_tetris_stats/game_data_processor/top_data_processor/processor.py @@ -3,15 +3,21 @@ from dataclasses import dataclass from io import StringIO from re import match from typing import Literal -from urllib.parse import urlencode +from urllib.parse import urlencode, urlunparse from lxml import etree +from nonebot_plugin_alconna.uniseg import UniMessage from nonebot_plugin_orm import get_session +from nonebot_plugin_userinfo import UserInfo # type: ignore[import-untyped] from pandas import read_html -from ...db import create_or_update_bind +from ...db import BindStatus, create_or_update_bind +from ...utils.avatar import get_avatar from ...utils.exception import MessageFormatError, RequestError +from ...utils.host import HostPage, get_self_netloc +from ...utils.render import render from ...utils.request import Request, splice_url +from ...utils.screenshot import screenshot from .. import Processor as ProcessorMeta from ..schemas import BaseUser from .constant import BASE_URL, GAME_TYPE @@ -60,18 +66,38 @@ class Processor(ProcessorMeta): def game_platform(self) -> Literal['TOP']: return GAME_TYPE - async def handle_bind(self, platform: str, account: str) -> str: + async def handle_bind(self, platform: str, account: str, bot_info: UserInfo, user_info: UserInfo) -> UniMessage: """处理绑定消息""" self.command_type = 'bind' await self.check_user() async with get_session() as session: - return await create_or_update_bind( + bind_status = await create_or_update_bind( session=session, chat_platform=platform, chat_account=account, game_platform=GAME_TYPE, game_account=self.user.name, ) + bot_avatar = await get_avatar(bot_info, 'Data URI', '../../static/logo/logo.svg') + if bind_status in (BindStatus.SUCCESS, BindStatus.UPDATE): + async with HostPage( + await render( + 'bind.j2.html', + user_avatar='../../static/static/logo/top.ico', + state='unknown', + bot_avatar=bot_avatar, + game_type=self.game_platform, + user_name=(await self.get_user_name()).upper(), + bot_name=bot_info.user_name, + command='top查我', + ) + ) as page_hash: + message = UniMessage.image( + raw=await screenshot( + urlunparse(('http', get_self_netloc(), f'/host/page/{page_hash}.html', '', '', '')) + ) + ) + return message async def handle_query(self) -> str: """处理查询消息""" diff --git a/nonebot_plugin_tetris_stats/game_data_processor/tos_data_processor/__init__.py b/nonebot_plugin_tetris_stats/game_data_processor/tos_data_processor/__init__.py index f311efb..fcc8677 100644 --- a/nonebot_plugin_tetris_stats/game_data_processor/tos_data_processor/__init__.py +++ b/nonebot_plugin_tetris_stats/game_data_processor/tos_data_processor/__init__.py @@ -5,6 +5,7 @@ from nonebot.adapters import Bot, Event from nonebot.matcher import Matcher from nonebot_plugin_alconna import At, on_alconna from nonebot_plugin_orm import get_session +from nonebot_plugin_userinfo import BotUserInfo, UserInfo # type: ignore[import-untyped] from ...db import query_bind_info from ...utils.exception import HandleNotFinishedError, NeedCatchError, RequestError @@ -130,17 +131,20 @@ except ImportError: @alc.assign('bind') -async def _(bot: Bot, event: Event, matcher: Matcher, account: User): +async def _(bot: Bot, event: Event, matcher: Matcher, account: User, bot_info: UserInfo = BotUserInfo()): # noqa: B008 proc = Processor( event_id=id(event), user=account, command_args=[], ) try: - await matcher.finish(await proc.handle_bind(platform=get_platform(bot), account=event.get_user_id())) + await ( + await proc.handle_bind(platform=get_platform(bot), account=event.get_user_id(), bot_info=bot_info) + ).send() except NeedCatchError as e: await matcher.send(str(e)) raise HandleNotFinishedError from e + await matcher.finish() @alc.assign('query') diff --git a/nonebot_plugin_tetris_stats/game_data_processor/tos_data_processor/processor.py b/nonebot_plugin_tetris_stats/game_data_processor/tos_data_processor/processor.py index 14724a4..679ff31 100644 --- a/nonebot_plugin_tetris_stats/game_data_processor/tos_data_processor/processor.py +++ b/nonebot_plugin_tetris_stats/game_data_processor/tos_data_processor/processor.py @@ -1,15 +1,21 @@ from dataclasses import dataclass from re import match from typing import Literal -from urllib.parse import urlencode +from urllib.parse import urlencode, urlunparse from httpx import TimeoutException from nonebot.compat import type_validate_json +from nonebot_plugin_alconna.uniseg import UniMessage from nonebot_plugin_orm import get_session +from nonebot_plugin_userinfo import UserInfo as NBUserInfo # type: ignore[import-untyped] -from ...db import create_or_update_bind +from ...db import BindStatus, create_or_update_bind +from ...utils.avatar import get_avatar from ...utils.exception import MessageFormatError, RequestError +from ...utils.host import HostPage, get_self_netloc +from ...utils.render import render from ...utils.request import Request, splice_url +from ...utils.screenshot import screenshot from .. import Processor as ProcessorMeta from ..schemas import BaseUser from .constant import BASE_URL, GAME_TYPE @@ -73,18 +79,39 @@ class Processor(ProcessorMeta): def game_platform(self) -> Literal['TOS']: return GAME_TYPE - async def handle_bind(self, platform: str, account: str) -> str: + async def handle_bind(self, platform: str, account: str, bot_info: NBUserInfo) -> UniMessage: """处理绑定消息""" self.command_type = 'bind' await self.get_user() async with get_session() as session: - return await create_or_update_bind( + bind_status = await create_or_update_bind( session=session, chat_platform=platform, chat_account=account, game_platform=GAME_TYPE, game_account=self.user.unique_identifier, ) + bot_avatar = await get_avatar(bot_info, 'Data URI', '../../static/logo/logo.svg') + user_info = await self.get_user_info() + if bind_status in (BindStatus.SUCCESS, BindStatus.UPDATE): + async with HostPage( + await render( + 'bind.j2.html', + user_avatar='../../static/static/logo/tos.ico', + state='unknown', + bot_avatar=bot_avatar, + game_type=self.game_platform, + user_name=user_info.data.name.upper(), + bot_name=bot_info.user_name, + command='茶服查我', + ) + ) as page_hash: + message = UniMessage.image( + raw=await screenshot( + urlunparse(('http', get_self_netloc(), f'/host/page/{page_hash}.html', '', '', '')) + ) + ) + return message async def handle_query(self) -> str: """处理查询消息""" diff --git a/nonebot_plugin_tetris_stats/templates/__init__.py b/nonebot_plugin_tetris_stats/templates/__init__.py new file mode 100644 index 0000000..ce5977f --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/__init__.py @@ -0,0 +1,3 @@ +from pathlib import Path + +path = Path(__file__).absolute().parent diff --git a/nonebot_plugin_tetris_stats/templates/bind.j2.html b/nonebot_plugin_tetris_stats/templates/bind.j2.html new file mode 100644 index 0000000..0377423 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/bind.j2.html @@ -0,0 +1,43 @@ + + + + + + + + + + +
+
+
+
+ + + +
+
+ 已将您在 +

{{ game_type }}

+ 上的账号 +
+

{{ user_name }}

+
+ {% if state == 'success' %} 成功验证并绑定至 +

{{ bot_name }}.

+ {% elif state == 'unverified'%} 绑定至 +

{{ bot_name }}

+ , 但尚未通过验证. {% elif state == 'unknown' %} 绑定至 +

{{ bot_name }}

+ ,
但是 +

{{ bot_name }}

+ 暂时无法验证您的身份. {% elif state == 'unlink' %} 成功从 +

{{ bot_name }}

+ 解绑. {% endif %} +
+
+
您可以输入 “{{ command }}” 命令来查找您在该平台上的统计数据.
+
+
+ + diff --git a/nonebot_plugin_tetris_stats/templates/css/bind.css b/nonebot_plugin_tetris_stats/templates/css/bind.css new file mode 100644 index 0000000..c9838ee --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/css/bind.css @@ -0,0 +1,118 @@ +@font-face { + font-family: 'SourceHanSansSC-VF'; + src: url('../static/fonts/SourceHanSans/SourceHanSansSC-VF.otf.woff2') format('woff2'); + font-display: swap; + font-style: normal; +} + +@font-face { + font-family: 'CabinetGrotesk-Variable'; + src: url('../static/fonts/CabinetGrotesk/CabinetGrotesk-Variable.woff2') format('woff2'); + font-display: swap; + font-style: normal; +} + +* { + margin: 0; + padding: 0; +} + +#background { + display: flex; + flex-direction: column; + align-items: flex-start; + padding: 30px; + gap: 10px; + + width: 444px; + + background: #f1f1f1; + font-family: 'CabinetGrotesk-Variable', 'SourceHanSansSC-VF'; +} + +#main-content { + display: flex; + flex-direction: column; + margin: 0 auto; + padding: 0px; + gap: 15px; +} + +#bind-subject { + display: flex; + flex-direction: column; + align-items: center; + padding: 0px; + gap: 30px; +} + +#bind-icons { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 0px; + gap: 32px; +} + +#user-avatar { + width: 96px; + height: 96px; + + filter: drop-shadow(0px 11px 23px rgba(0, 0, 0, 0.22)); + border-radius: 20px; +} + +#state { + width: 128px; + height: 56px; +} + +#bot-avatar { + width: 96px; + height: 96px; + + filter: drop-shadow(0px 11px 23px rgba(0, 0, 0, 0.22)); + border-radius: 20px; +} + +#command-result { + font-weight: 350; + font-size: 25px; + line-height: 36.2px; + text-align: center; + + color: #000000; +} + +#game-type { + display: inline; + font-weight: 800; + line-height: 31px; +} + +#user-name { + display: inline; + font-weight: 800; + line-height: 31px; + white-space: nowrap; + text-overflow: ellipsis; +} + +#bot-name { + display: inline; + font-weight: 400; + line-height: 31px; +} + +#extra-info { + width: 324px; + + margin: 0 auto; + font-weight: 400; + font-size: 16px; + line-height: 23px; + text-align: center; + + color: #52525c; +} diff --git a/nonebot_plugin_tetris_stats/templates/css/data.css b/nonebot_plugin_tetris_stats/templates/css/data.css new file mode 100644 index 0000000..068f5ef --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/css/data.css @@ -0,0 +1,351 @@ +@font-face { + font-family: 'CabinetGrotesk-Variable'; + src: url('../static/fonts/CabinetGrotesk/CabinetGrotesk-Variable.woff2') format('woff2'); +} + +@font-face { + font-family: '26FGalaxySans-ObliqueVF'; + src: url('../static/fonts/26FGalaxySans/26FGalaxySans-ObliqueVF.woff2') format('woff2'); +} + +* { + margin: 0; + padding: 0; +} + +.flex-gap { + flex: 1; +} + +.big-title { + margin-left: 25px; + margin-top: 22px; + + font-weight: 900; + font-size: 35px; + line-height: 43px; + + color: #000000; +} + +.box-shadow { + box-shadow: 0px 9px 25px rgba(0, 0, 0, 0.15); +} + +.chart-shadow { + box-shadow: 0px 15px 30px rgba(0, 0, 0, 0.3); +} + +.box-rounded-corners { + border-radius: 30px; +} + +.small-data-box { + position: relative; + width: 275px; + height: 125px; +} + +.big-data-value { + position: absolute; + left: 24px; + top: 52px; + + font-weight: 500; + font-size: 45px; + line-height: 56px; +} + +.small-data-value { + position: absolute; + top: 79px; + right: 25px; + + font-weight: 500; + font-size: 15px; + line-height: 19px; + text-align: right; +} + +#main-content { + display: flex; + flex-direction: column; + + width: 625px; + + background: #f1f1f1; + font-family: 'CabinetGrotesk-Variable'; +} + +#account-box { + display: flex; + flex-direction: column; +} + +#info-box { + display: flex; + justify-content: space-between; + margin-top: 10px; +} + +#user-info-box { + display: flex; + flex-direction: column; + align-items: center; + padding: 25px; + gap: 10px; + + width: 275px; + height: 275px; + + background: #fafafa; + + box-sizing: border-box; +} + +#user-avatar { + width: 125px; + height: 125px; + filter: drop-shadow(0px 11px 23px rgba(0, 0, 0, 0.22)); + border-radius: 65px; +} + +#user-name { + font-weight: 800; + font-size: 25px; + line-height: 31px; + + color: #000000; +} + +#user-sign { + width: 225px; + height: 66px; + + font-weight: 400; + font-size: 18px; + line-height: 22px; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + + color: #000000; +} + +#game-info-box { + display: flex; + flex-direction: column; + align-items: flex-start; + padding: 25px; + gap: 10px; + + width: 275px; + height: 275px; + + background: #fafafa; + + box-sizing: border-box; +} + +#game-type-box { + display: flex; + flex-direction: column; +} + +#game-logo { + width: 60px; + height: 60px; + + border-radius: 10px; +} + +#game-name { + font-weight: 800; + font-size: 30px; + line-height: 37px; + + color: #000000; +} + +#game-info-dividing-line { + width: 225px; + border: 1px solid #bababa; + transform: rotate(0.25deg); +} + +#ranking-info-box { + display: flex; + flex-direction: column; +} + +#ranking-title { + font-weight: 800; + font-size: 25px; + line-height: 31px; + + color: #000000; +} + +#ranking { + font-weight: 400; + font-size: 50px; + line-height: 120%; + + color: #000000; +} + +#rd { + margin-top: -16px; + + font-weight: 300; + font-size: 30px; + line-height: 120%; + + color: #000000; +} + +#TR-curve-chart { + align-self: center; + margin-top: 25px; + + width: 575px; + height: 275px; + + background: linear-gradient(222.34deg, #525252 11.97%, #1d1916 89.73%); +} + +#TR-title { + position: absolute; + margin-left: 24px; + margin-top: 19px; + + font-weight: 800; + font-size: 25px; + line-height: 31px; + white-space: nowrap; + + color: #fafafa; +} + +#rank-icon { + position: absolute; + margin-left: 27px; + margin-top: 90px; + + width: 50px; + height: 50px; +} + +#TR { + position: absolute; + margin-left: 24px; + margin-top: 143px; + + font-weight: 800; + font-size: 45px; + line-height: 120%; + + color: #fafafa; +} + +#multiplayer-box { + display: flex; + flex-direction: row; + justify-content: space-between; + margin-top: 14px; +} + +#multiplayer-data-box { + display: flex; + flex-direction: column; +} + +.multiplayer-data { + margin-top: 25px; +} + +.multiplayer-data:first-child { + margin-top: 0px; +} + +#lpm-box { + background-image: url('../static/data/LPM.svg'); +} + +#lpm-value { + color: #4d7d0f; +} + +#pps-value { + color: #4d7d0f; +} + +#apm-box { + background-image: url('../static/data/APM.svg'); +} + +#apm-value { + color: #b5530a; +} + +#apl-value { + color: #b5530a; +} + +#adpm-box { + background-image: url('../static/data/ADPM.svg'); +} + +#adpm-value { + color: #235db4; +} + +#vs-value { + top: 62px; + color: #4779c6; +} + +#adpl-value { + color: #4779c6; +} + +#radar-chart { + width: 275px; + height: 275px; + background: linear-gradient(222.34deg, #525252 11.97%, #1d1916 89.73%), + linear-gradient(222.34deg, #4f9dff 11.97%, #2563ea 89.73%); +} + +#singleplayer-box { + display: flex; + flex-direction: row; + align-content: space-between; + margin-top: 14px; +} + +#sprint-box { + background-image: url('../static/data/40L.svg'); +} + +#blitz-box { + background-image: url('../static/data/Blitz.svg'); +} + +#sprint-value { + color: #b42323; +} + +#blitz-value { + color: #8e23b4; +} + +#footer { + display: flex; + justify-content: center; + margin-top: 20px; + margin-bottom: 20px; + font-family: '26FGalaxySans-ObliqueVF'; + font-size: 32px; + font-weight: 257; + text-align: center; +} diff --git a/nonebot_plugin_tetris_stats/templates/data.j2.html b/nonebot_plugin_tetris_stats/templates/data.j2.html new file mode 100644 index 0000000..603ed41 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/data.j2.html @@ -0,0 +1,352 @@ + + + + + + + + + + +
+ Account&Rankings +
+
+
+
+ +
{{user_name}}
+
“{{user_sign}}”
+
+
+
+
+ + {{game_type}} +
+
+
+ Ranking + {{ranking}} + ±{{rd}} +
+
+
+
+
+ Tetra Rating (TR) + + {{TR}}  +

(#{{global_rank}})

+
+
+
+ Multiplayer Stats +
+
+
+
+ {{lpm}} + {{pps}} pps +
+
+ {{apm}} + x{{apl}} +
+
+ {{adpm}} + x{{adpl}} + {{vs}} vs +
+
+
+
+
+
+ Singleplayer Stats +
+
+
+ {{sprint}} +
+
+
+ {{blitz}} +
+
+
+ +
+ + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/js/echarts.js b/nonebot_plugin_tetris_stats/templates/js/echarts.js new file mode 100644 index 0000000..1f1619d --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/js/echarts.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).echarts={})}(this,function(t){"use strict";var v=function(t,e){return(v=Object.setPrototypeOf||({__proto__:[]}instanceof Array?function(t,e){t.__proto__=e}:function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])}))(t,e)};function u(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function n(){this.constructor=t}v(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}var x=function(){this.firefox=!1,this.ie=!1,this.edge=!1,this.newEdge=!1,this.weChat=!1},p=new function(){this.browser=new x,this.node=!1,this.wxa=!1,this.worker=!1,this.svgSupported=!1,this.touchEventsSupported=!1,this.pointerEventsSupported=!1,this.domSupported=!1,this.transformSupported=!1,this.transform3dSupported=!1,this.hasGlobalWindow="undefined"!=typeof window};"object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?(p.wxa=!0,p.touchEventsSupported=!0):"undefined"==typeof document&&"undefined"!=typeof self?p.worker=!0:"undefined"==typeof navigator||0===navigator.userAgent.indexOf("Node.js")?(p.node=!0,p.svgSupported=!0):(et=navigator.userAgent,ae=(Wt=p).browser,at=et.match(/Firefox\/([\d.]+)/),q=et.match(/MSIE\s([\d.]+)/)||et.match(/Trident\/.+?rv:(([\d.]+))/),tt=et.match(/Edge?\/([\d.]+)/),et=/micromessenger/i.test(et),at&&(ae.firefox=!0,ae.version=at[1]),q&&(ae.ie=!0,ae.version=q[1]),tt&&(ae.edge=!0,ae.version=tt[1],ae.newEdge=18<+tt[1].split(".")[0]),et&&(ae.weChat=!0),Wt.svgSupported="undefined"!=typeof SVGRect,Wt.touchEventsSupported="ontouchstart"in window&&!ae.ie&&!ae.edge,Wt.pointerEventsSupported="onpointerdown"in window&&(ae.edge||ae.ie&&11<=+ae.version),Wt.domSupported="undefined"!=typeof document,at=document.documentElement.style,Wt.transform3dSupported=(ae.ie&&"transition"in at||ae.edge||"WebKitCSSMatrix"in window&&"m11"in new WebKitCSSMatrix||"MozPerspective"in at)&&!("OTransition"in at),Wt.transformSupported=Wt.transform3dSupported||ae.ie&&9<=+ae.version);var w=12,b="sans-serif",K=w+"px "+b;var S,T,C=function(t){var e={};if("undefined"!=typeof JSON)for(var n=0;n>1)%2;s.cssText=["position: absolute","visibility: hidden","padding: 0","margin: 0","border-width: 0","user-select: none","width:0","height:0",i[l]+":0",r[u]+":0",i[1-l]+":auto",r[1-u]+":auto",""].join("!important;"),t.appendChild(a),n.push(a)}}return n}(e,o),o,r);if(e)return e(t,n,i),1}}function me(t){return"CANVAS"===t.nodeName.toUpperCase()}var ve=/([&<>"'])/g,_e={"&":"&","<":"<",">":">",'"':""","'":"'"};function xe(t){return null==t?"":(t+"").replace(ve,function(t,e){return _e[e]})}var we=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,be=[],Se=p.browser.firefox&&+p.browser.version.split(".")[0]<39;function Me(t,e,n,i){return n=n||{},i?Te(t,e,n):Se&&null!=e.layerX&&e.layerX!==e.offsetX?(n.zrX=e.layerX,n.zrY=e.layerY):null!=e.offsetX?(n.zrX=e.offsetX,n.zrY=e.offsetY):Te(t,e,n),n}function Te(t,e,n){if(p.domSupported&&t.getBoundingClientRect){var i,r=e.clientX,e=e.clientY;if(me(t))return i=t.getBoundingClientRect(),n.zrX=r-i.left,void(n.zrY=e-i.top);if(ye(be,t,r,e))return n.zrX=be[0],void(n.zrY=be[1])}n.zrX=n.zrY=0}function Ce(t){return t||window.event}function Ie(t,e,n){var i;return null==(e=Ce(e)).zrX&&((i=e.type)&&0<=i.indexOf("touch")?(i=("touchend"!==i?e.targetTouches:e.changedTouches)[0])&&Me(t,i,e,n):(Me(t,e,e,n),i=function(t){var e=t.wheelDelta;if(e)return e;var n=t.deltaX,t=t.deltaY;return null!=n&&null!=t?3*(0!==t?Math.abs(t):Math.abs(n))*(0=n.x&&t<=n.x+n.width&&e>=n.y&&e<=n.y+n.height},Ke.prototype.clone=function(){return new Ke(this.x,this.y,this.width,this.height)},Ke.prototype.copy=function(t){Ke.copy(this,t)},Ke.prototype.plain=function(){return{x:this.x,y:this.y,width:this.width,height:this.height}},Ke.prototype.isFinite=function(){return isFinite(this.x)&&isFinite(this.y)&&isFinite(this.width)&&isFinite(this.height)},Ke.prototype.isZero=function(){return 0===this.width||0===this.height},Ke.create=function(t){return new Ke(t.x,t.y,t.width,t.height)},Ke.copy=function(t,e){t.x=e.x,t.y=e.y,t.width=e.width,t.height=e.height},Ke.applyTransform=function(t,e,n){var i,r,o,a;n?n[1]<1e-5&&-1e-5t.getWidth()||n<0||n>t.getHeight()}N(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],function(a){sn.prototype[a]=function(t){var e,n,i=t.zrX,r=t.zrY,o=hn(this,i,r);if("mouseup"===a&&o||(n=(e=this.findHover(i,r)).target),"mousedown"===a)this._downEl=n,this._downPoint=[t.zrX,t.zrY],this._upEl=n;else if("mouseup"===a)this._upEl=n;else if("click"===a){if(this._downEl!==this._upEl||!this._downPoint||4>>1])<0?l=o:s=1+o;var u=i-s;switch(u){case 3:t[s+3]=t[s+2];case 2:t[s+2]=t[s+1];case 1:t[s+1]=t[s];break;default:for(;0>>1);0>>1);o(t,e[n+h])<0?l=h:a=h+1}return l}function mn(A,L){var P,O,N=pn,R=0,E=[];function e(t){var e=P[t],n=O[t],i=P[t+1],r=O[t+1],t=(O[t]=n+r,t===R-3&&(P[t+1]=P[t+2],O[t+1]=O[t+2]),R--,yn(A[i],A,e,n,0,L));if(e+=t,0!=(n-=t)&&0!==(r=gn(A[e+n-1],A,i,r,r-1,L)))if(n<=r){var o=e,a=n,t=i,s=r,l=0;for(l=0;lO[t+1])break;e(t)}},forceMergeRuns:function(){for(;1>=1;return t+e}(r);do{}while((o=dn(t,n,i,e))=this._maxSize&&0>4|(3840&r)>>8,240&r|(240&r)>>4,15&r|(15&r)<<4,5===i?parseInt(n.slice(4),16)/15:1),gi(t,e),e):void ci(e,0,0,0,1):7===i||9===i?0<=(r=parseInt(n.slice(1,7),16))&&r<=16777215?(ci(e,(16711680&r)>>16,(65280&r)>>8,255&r,9===i?parseInt(n.slice(7),16)/255:1),gi(t,e),e):void ci(e,0,0,0,1):void 0;var r=n.indexOf("("),o=n.indexOf(")");if(-1!==r&&o+1===i){var i=n.substr(0,r),a=n.substr(r+1,o-(r+1)).split(","),s=1;switch(i){case"rgba":if(4!==a.length)return 3===a.length?ci(e,+a[0],+a[1],+a[2],1):ci(e,0,0,0,1);s=li(a.pop());case"rgb":return 3<=a.length?(ci(e,si(a[0]),si(a[1]),si(a[2]),3===a.length?s:li(a[3])),gi(t,e),e):void ci(e,0,0,0,1);case"hsla":return 4!==a.length?void ci(e,0,0,0,1):(a[3]=li(a[3]),mi(a,e),gi(t,e),e);case"hsl":return 3!==a.length?void ci(e,0,0,0,1):(mi(a,e),gi(t,e),e);default:return}}ci(e,0,0,0,1)}}function mi(t,e){var n=(parseFloat(t[0])%360+360)%360/360,i=li(t[1]),r=li(t[2]),i=r<=.5?r*(i+1):r+i-r*i,r=2*r-i;return ci(e=e||[],oi(255*ui(r,i,n+1/3)),oi(255*ui(r,i,n)),oi(255*ui(r,i,n-1/3)),1),4===t.length&&(e[3]=t[3]),e}function vi(t,e){var n=yi(t);if(n){for(var i=0;i<3;i++)n[i]=e<0?n[i]*(1-e)|0:(255-n[i])*e+n[i]|0,255e);g++);g=f(g-1,h-2)}i=u[g+1],n=u[g]}n&&i&&(this._lastFr=g,this._lastFrP=e,d=i.percent-n.percent,r=0==d?1:f((e-n.percent)/d,1),i.easingFunc&&(r=i.easingFunc(r)),f=a?this._additiveValue:p?Ki:t[c],(Zi(l)||p)&&(f=f||(this._additiveValue=[])),this.discrete?t[c]=(r<1?n:i).rawValue:Zi(l)?(1===l?Wi:function(t,e,n,i){for(var r=e.length,o=r&&e[0].length,a=0;athis._sleepAfterStill)&&this.animation.stop()},co.prototype.setSleepAfterStill=function(t){this._sleepAfterStill=t},co.prototype.wakeUp=function(){this._disposed||(this.animation.start(),this._stillFrameAccum=0)},co.prototype.refreshHover=function(){this._needsRefreshHover=!0},co.prototype.refreshHoverImmediately=function(){this._disposed||(this._needsRefreshHover=!1,this.painter.refreshHover&&"canvas"===this.painter.getType()&&this.painter.refreshHover())},co.prototype.resize=function(t){this._disposed||(this.painter.resize((t=t||{}).width,t.height),this.handler.resize())},co.prototype.clearAnimation=function(){this._disposed||this.animation.clear()},co.prototype.getWidth=function(){if(!this._disposed)return this.painter.getWidth()},co.prototype.getHeight=function(){if(!this._disposed)return this.painter.getHeight()},co.prototype.setCursorStyle=function(t){this._disposed||this.handler.setCursorStyle(t)},co.prototype.findHover=function(t,e){if(!this._disposed)return this.handler.findHover(t,e)},co.prototype.on=function(t,e,n){return this._disposed||this.handler.on(t,e,n),this},co.prototype.off=function(t,e){this._disposed||this.handler.off(t,e)},co.prototype.trigger=function(t,e){this._disposed||this.handler.trigger(t,e)},co.prototype.clear=function(){if(!this._disposed){for(var t=this.storage.getRoots(),e=0;e=e.maxIterations){t+=e.ellipsis;break}var s=0===a?function(t,e,n,i){for(var r=0,o=0,a=t.length;oo){0i.width&&(o=e.split("\n"),c=!0),i.accumWidth=t):(t=La(e,h,i.width,i.breakAll,i.accumWidth),i.accumWidth=t.accumWidth+n,a=t.linesWidths,o=t.lines)):o=e.split("\n");for(var p=0;pthis._ux||i>this._uy;return this.addData(Y.L,t,e),this._ctx&&r&&this._ctx.lineTo(t,e),r?(this._xi=t,this._yi=e,this._pendingPtDist=0):(r=n*n+i*i)>this._pendingPtDist&&(this._pendingPtX=t,this._pendingPtY=e,this._pendingPtDist=r),this},o.prototype.bezierCurveTo=function(t,e,n,i,r,o){return this._drawPendingPt(),this.addData(Y.C,t,e,n,i,r,o),this._ctx&&this._ctx.bezierCurveTo(t,e,n,i,r,o),this._xi=r,this._yi=o,this},o.prototype.quadraticCurveTo=function(t,e,n,i){return this._drawPendingPt(),this.addData(Y.Q,t,e,n,i),this._ctx&&this._ctx.quadraticCurveTo(t,e,n,i),this._xi=n,this._yi=i,this},o.prototype.arc=function(t,e,n,i,r,o){this._drawPendingPt(),cs[0]=i,cs[1]=r,s=o,(l=ps((a=cs)[0]))<0&&(l+=us),h=l-a[0],u=a[1],u+=h,!s&&us<=u-l?u=l+us:s&&us<=l-u?u=l-us:!s&&uu.length&&(this._expandData(),u=this.data);for(var h=0;hn||ss(y)>i||c===e-1)&&(f=Math.sqrt(I*I+y*y),r=g,o=_);break;case Y.C:var m=t[c++],v=t[c++],g=t[c++],_=t[c++],x=t[c++],w=t[c++],f=function(t,e,n,i,r,o,a,s,l){for(var u=t,h=e,c=0,p=1/l,d=1;d<=l;d++){var f=d*p,g=Bn(t,n,r,a,f),f=Bn(e,i,o,s,f),y=g-u,m=f-h;c+=Math.sqrt(y*y+m*m),u=g,h=f}return c}(r,o,m,v,g,_,x,w,10),r=x,o=w;break;case Y.Q:f=function(t,e,n,i,r,o,a){for(var s=t,l=e,u=0,h=1/a,c=1;c<=a;c++){var p=c*h,d=Un(t,n,r,p),p=Un(e,i,o,p),f=d-s,g=p-l;u+=Math.sqrt(f*f+g*g),s=d,l=p}return u}(r,o,m=t[c++],v=t[c++],g=t[c++],_=t[c++],10),r=g,o=_;break;case Y.A:var x=t[c++],w=t[c++],b=t[c++],S=t[c++],M=t[c++],T=t[c++],C=T+M;c+=1,d&&(a=os(M)*b+x,s=as(M)*S+w),f=rs(b,S)*is(us,Math.abs(T)),r=os(C)*b+x,o=as(C)*S+w;break;case Y.R:a=r=t[c++],s=o=t[c++];f=2*t[c++]+2*t[c++];break;case Y.Z:var I=a-r,y=s-o;f=Math.sqrt(I*I+y*y),r=a,o=s}0<=f&&(u+=l[h++]=f)}return this._pathLen=u},o.prototype.rebuildPath=function(t,e){var n,i,r,o,a,s,l,u,h=this.data,E=this._ux,z=this._uy,B=this._len,c=e<1,p=0,d=0,f=0;if(!c||(this._pathSegLen||this._calculateLength(),a=this._pathSegLen,s=e*this._pathLen))t:for(var g=0;g=bs[i=0]+t&&a<=bs[1]+t?h:0;rMath.PI/2&&c<1.5*Math.PI?-h:h)}return l}(y,m,_,x,x+w,b,T,r);u=Math.cos(x+w)*v+y,h=Math.sin(x+w)*_+m;break;case _s.R:c=u=a[d++],p=h=a[d++];if(S=c+a[d++],M=p+a[d++],n){if(fs(c,p,S,p,e,i,r)||fs(S,p,S,M,e,i,r)||fs(S,M,c,M,e,i,r)||fs(c,M,c,p,e,i,r))return!0}else l=(l+=vs(S,p,S,M,i,r))+vs(c,M,c,p,i,r);break;case _s.Z:if(n){if(fs(u,h,c,p,e,i,r))return!0}else l+=vs(u,h,c,p,i,r);u=c,h=p}}return n||(t=h,o=p,Math.abs(t-o)i.len()&&(uMath.abs(i[1])?0e)return t[i];return t[n-1]}var kd,Dd="\0_ec_inner",Ad=(u(s,kd=tp),s.prototype.init=function(t,e,n,i,r,o){i=i||{},this.option=null,this._theme=new tp(i),this._locale=new tp(r),this._optionManager=o},s.prototype.setOption=function(t,e,n){e=Od(e);this._optionManager.setOption(t,n,e),this._resetOption(null,e)},s.prototype.resetOption=function(t,e){return this._resetOption(t,Od(e))},s.prototype._resetOption=function(t,e){var n,i=!1,r=this._optionManager;return t&&"recreate"!==t||(n=r.mountOption("recreate"===t),this.option&&"recreate"!==t?(this.restoreData(),this._mergeOption(n,e)):Sd(this,n),i=!0),"timeline"!==t&&"media"!==t||this.restoreData(),t&&"recreate"!==t&&"timeline"!==t||(n=r.getTimelineOption(this))&&(i=!0,this._mergeOption(n,e)),t&&"recreate"!==t&&"media"!==t||(n=r.getMediaOption(this)).length&&N(n,function(t){i=!0,this._mergeOption(t,e)},this),i},s.prototype.mergeOption=function(t){this._mergeOption(t,null)},s.prototype._mergeOption=function(i,t){var r=this.option,h=this._componentsMap,c=this._componentsCount,n=[],o=G(),p=t&&t.replaceMergeMainTypeMap;yd(this).datasetMap=G(),N(i,function(t,e){null!=t&&(g.hasClass(e)?e&&(n.push(e),o.set(e,!0)):r[e]=null==r[e]?_(t):d(r[e],t,!0))}),p&&p.each(function(t,e){g.hasClass(e)&&!o.get(e)&&(n.push(e),o.set(e,!0))}),g.topologicalTravel(n,g.getAllClassMainTypes(),function(o){var a,t=function(t,e,n){return(e=(e=xd.get(e))&&e(t))?n.concat(e):n}(this,o,zo(i[o])),e=h.get(o),n=e?p&&p.get(o)?"replaceMerge":"normalMerge":"replaceAll",e=Ho(e,t,n),s=(qo(e,o,g),r[o]=null,h.set(o,null),c.set(o,0),[]),l=[],u=0;N(e,function(t,e){var n=t.existing,i=t.newOption;if(i){var r=g.getClass(o,t.keyInfo.subType,!("series"===o));if(!r)return;if("tooltip"===o){if(a)return;a=!0}n&&n.constructor===r?(n.name=t.keyInfo.name,n.mergeOption(i,this),n.optionUpdated(i,!1)):(e=O({componentIndex:e},t.keyInfo),O(n=new r(i,this,this,e),e),t.brandNew&&(n.__requireNewView=!0),n.init(i,this,this),n.optionUpdated(null,!0))}else n&&(n.mergeOption({},this),n.optionUpdated({},!1));n?(s.push(n.option),l.push(n),u++):(s.push(void 0),l.push(void 0))},this),r[o]=s,h.set(o,l),c.set(o,u),"series"===o&&wd(this)},this),this._seriesIndices||wd(this)},s.prototype.getOption=function(){var a=_(this.option);return N(a,function(t,e){if(g.hasClass(e)){for(var n=zo(t),i=n.length,r=!1,o=i-1;0<=o;o--)n[o]&&!Yo(n[o])?r=!0:(n[o]=null,r||i--);n.length=i,a[e]=n}}),delete a[Dd],a},s.prototype.getTheme=function(){return this._theme},s.prototype.getLocaleModel=function(){return this._locale},s.prototype.setUpdatePayload=function(t){this._payload=t},s.prototype.getUpdatePayload=function(){return this._payload},s.prototype.getComponent=function(t,e){var n=this._componentsMap.get(t);if(n){t=n[e||0];if(t)return t;if(null==e)for(var i=0;ig[1]&&(g[1]=f)}return{start:a,end:this._rawCount=this._count=s}},l.prototype._initDataFromProvider=function(t,e,n){for(var i=this._provider,r=this._chunks,o=this._dimensions,a=o.length,s=this._rawExtent,l=B(o,function(t){return t.property}),u=0;uf[1]&&(f[1]=g)}!i.persistent&&i.clean&&i.clean(),this._rawCount=this._count=e,this._extent=[]},l.prototype.count=function(){return this._count},l.prototype.get=function(t,e){return 0<=e&&e=this._rawCount||t<0)){if(!this._indices)return t;var e=this._indices,n=e[t];if(null!=n&&nt))return o;r=o-1}}}return-1},l.prototype.indicesOfNearest=function(t,e,n){var i=this._chunks[t],r=[];if(i){null==n&&(n=1/0);for(var o=1/0,a=-1,s=0,l=0,u=this.count();lt[S][1])&&(w=!1)}w&&(a[s++]=e.getRawIndex(f))}return sy[1]&&(y[1]=g)}}}},l.prototype.lttbDownSample=function(t,e){var n,i=this.clone([t],!0),r=i._chunks[t],o=this.count(),a=0,s=Math.floor(1/e),l=this.getRawIndex(0),u=new(xg(this._rawCount))(Math.min(2*(Math.ceil(o/s)+2),o));u[a++]=l;for(var h=1;hh[1]&&(h[1]=y),c[p++]=m}return r._count=p,r._indices=c,r._updateGetRawIdx(),r},l.prototype.each=function(t,e){if(this._count)for(var n=t.length,i=this._chunks,r=0,o=this.count();rthis.getShallow("animationThreshold")?!1:t)},h.prototype.restoreData=function(){this.dataTask.dirty()},h.prototype.getColorFromPalette=function(t,e,n){var i=this.ecModel;return Td.prototype.getColorFromPalette.call(this,t,e,n)||i.getColorFromPalette(t,e,n)},h.prototype.coordDimToDataDim=function(t){return this.getRawData().mapDimensionsAll(t)},h.prototype.getProgressive=function(){return this.get("progressive")},h.prototype.getProgressiveThreshold=function(){return this.get("progressiveThreshold")},h.prototype.select=function(t,e){this._innerSelect(this.getData(e),t)},h.prototype.unselect=function(t,e){var n=this.option.selectedMap;if(n){var i=this.option.selectedMode,r=this.getData(e);if("series"===i||"all"===n)this.option.selectedMap={},this._selectedDataIndicesMap={};else for(var o=0;oe.outputData.count()&&e.model.getRawData().cloneShallow(e.outputData)}function Hg(e,n){N(zt(e.CHANGABLE_METHODS,e.DOWNSAMPLE_METHODS),function(t){e.wrapMethod(t,ft(Gg,n))})}function Gg(t,e){t=Wg(t);return t&&t.setOutputEnd((e||this).count()),e}function Wg(t){var e,n=(t.ecModel||{}).scheduler,n=n&&n.getPipeline(t.uid);if(n)return(n=n.currentTask)&&(e=n.agentStubMap)?e.get(t.uid):n}lt(Eg,$c),lt(Eg,Td),la(Eg,g);Xg.prototype.init=function(t,e){},Xg.prototype.render=function(t,e,n,i){},Xg.prototype.dispose=function(t,e){},Xg.prototype.updateView=function(t,e,n,i){},Xg.prototype.updateLayout=function(t,e,n,i){},Xg.prototype.updateVisual=function(t,e,n,i){},Xg.prototype.toggleBlurSeries=function(t,e,n){},Xg.prototype.eachRendered=function(t){var e=this.group;e&&e.traverse(t)};var Ug=Xg;function Xg(){this.group=new oo,this.uid=ip("viewComponent")}function Yg(){var o=Zo();return function(t){var e=o(t),t=t.pipelineContext,n=!!e.large,i=!!e.progressiveRender,r=e.large=!(!t||!t.large),e=e.progressiveRender=!(!t||!t.progressiveRender);return!(n==r&&i==e)&&"reset"}}sa(Ug),pa(Ug);var qg=Zo(),jg=Yg(),Zg=(Kg.prototype.init=function(t,e){},Kg.prototype.render=function(t,e,n,i){},Kg.prototype.highlight=function(t,e,n,i){t=t.getData(i&&i.dataType);t&&Qg(t,i,"emphasis")},Kg.prototype.downplay=function(t,e,n,i){t=t.getData(i&&i.dataType);t&&Qg(t,i,"normal")},Kg.prototype.remove=function(t,e){this.group.removeAll()},Kg.prototype.dispose=function(t,e){},Kg.prototype.updateView=function(t,e,n,i){this.render(t,e,n,i)},Kg.prototype.updateLayout=function(t,e,n,i){this.render(t,e,n,i)},Kg.prototype.updateVisual=function(t,e,n,i){this.render(t,e,n,i)},Kg.prototype.eachRendered=function(t){Cc(this.group,t)},Kg.markUpdateMethod=function(t,e){qg(t).updateMethod=e},Kg.protoInitialize=void(Kg.prototype.type="chart"),Kg);function Kg(){this.group=new oo,this.uid=ip("viewChart"),this.renderTask=Bf({plan:Jg,reset:ty}),this.renderTask.context={view:this}}function $g(t,e,n){t&&su(t)&&("emphasis"===e?Wl:Ul)(t,n)}function Qg(e,t,n){var i,r=jo(e,t),o=t&&null!=t.highlightKey?(t=t.highlightKey,i=null==(i=fl[t])&&dl<=32?fl[t]=dl++:i):null;null!=r?N(zo(r),function(t){$g(e.getItemGraphicEl(t),n,o)}):e.eachItemGraphicEl(function(t){$g(t,n,o)})}function Jg(t){return jg(t.model)}function ty(t){var e=t.model,n=t.ecModel,i=t.api,r=t.payload,o=e.pipelineContext.progressiveRender,t=t.view,a=r&&qg(r).updateMethod,o=o?"incrementalPrepareRender":a&&t[a]?a:"render";return"render"!==o&&t[o](e,n,i,r),ey[o]}sa(Zg),pa(Zg);var ey={incrementalPrepareRender:{progress:function(t,e){e.view.incrementalRender(t,e.model,e.ecModel,e.api,e.payload)}},render:{forceFirstProgress:!0,progress:function(t,e){e.view.render(e.model,e.ecModel,e.api,e.payload)}}};function ny(t,r,o){var a,s,l,u,h,c=0,p=0,d=null;function f(){p=(new Date).getTime(),d=null,t.apply(l,u||[])}r=r||0;function e(){for(var t=[],e=0;en.blockIndex?n.step:null,modBy:null!=(t=i&&i.modDataCount)?Math.ceil(t/e):null,modDataCount:t}},cy.prototype.getPipeline=function(t){return this._pipelineMap.get(t)},cy.prototype.updateStreamModes=function(t,e){var n=this._pipelineMap.get(t.uid),i=t.getData().count(),e=n.progressiveEnabled&&e.incrementalPrepareRender&&i>=n.threshold,r=t.get("large")&&i>=t.get("largeThreshold"),i="mod"===t.get("progressiveChunkMode")?i:null;t.pipelineContext=n.context={progressiveRender:e,modDataCount:i,large:r}},cy.prototype.restorePipelines=function(t){var i=this,r=i._pipelineMap=G();t.eachSeries(function(t){var e=t.getProgressive(),n=t.uid;r.set(n,{id:n,head:null,tail:null,threshold:t.getProgressiveThreshold(),progressiveEnabled:e&&!(t.preventIncremental&&t.preventIncremental()),blockIndex:-1,step:Math.round(e||700),count:0}),i._pipe(t,t.dataTask)})},cy.prototype.prepareStageTasks=function(){var n=this._stageTaskMap,i=this.api.getModel(),r=this.api;N(this._allHandlers,function(t){var e=n.get(t.uid)||n.set(t.uid,{});It(!(t.reset&&t.overallReset),""),t.reset&&this._createSeriesStageTask(t,e,i,r),t.overallReset&&this._createOverallStageTask(t,e,i,r)},this)},cy.prototype.prepareView=function(t,e,n,i){var r=t.renderTask,o=r.context;o.model=e,o.ecModel=n,o.api=i,r.__block=!t.incrementalPrepareRender,this._pipe(e,r)},cy.prototype.performDataProcessorTasks=function(t,e){this._performStageTasks(this._dataProcessorHandlers,t,e,{block:!0})},cy.prototype.performVisualTasks=function(t,e,n){this._performStageTasks(this._visualHandlers,t,e,n)},cy.prototype._performStageTasks=function(t,s,l,u){u=u||{};var h=!1,c=this;function p(t,e){return t.setDirty&&(!t.dirtyMap||t.dirtyMap.get(e.__pipeline.id))}N(t,function(i,t){var e,n,r,o,a;u.visualType&&u.visualType!==i.visualType||(e=(n=c._stageTaskMap.get(i.uid)).seriesTaskMap,(n=n.overallTask)?((o=n.agentStubMap).each(function(t){p(u,t)&&(t.dirty(),r=!0)}),r&&n.dirty(),c.updatePayload(n,l),a=c.getPerformArgs(n,u.block),o.each(function(t){t.perform(a)}),n.perform(a)&&(h=!0)):e&&e.each(function(t,e){p(u,t)&&t.dirty();var n=c.getPerformArgs(t,u.block);n.skip=!i.performRawSeries&&s.isSeriesFiltered(t.context.model),c.updatePayload(t,l),t.perform(n)&&(h=!0)}))}),this.unfinished=h||this.unfinished},cy.prototype.performSeriesTasks=function(t){var e;t.eachSeries(function(t){e=t.dataTask.perform()||e}),this.unfinished=e||this.unfinished},cy.prototype.plan=function(){this._pipelineMap.each(function(t){var e=t.tail;do{if(e.__block){t.blockIndex=e.__idxInPipeline;break}}while(e=e.getUpstream())})},cy.prototype.updatePayload=function(t,e){"remain"!==e&&(t.context.payload=e)},cy.prototype._createSeriesStageTask=function(n,t,i,r){var o=this,a=t.seriesTaskMap,s=t.seriesTaskMap=G(),t=n.seriesType,e=n.getTargetSeries;function l(t){var e=t.uid,e=s.set(e,a&&a.get(e)||Bf({plan:yy,reset:my,count:xy}));e.context={model:t,ecModel:i,api:r,useClearVisual:n.isVisual&&!n.isLayout,plan:n.plan,reset:n.reset,scheduler:o},o._pipe(t,e)}n.createOnAllSeries?i.eachRawSeries(l):t?i.eachRawSeriesByType(t,l):e&&e(i,r).each(l)},cy.prototype._createOverallStageTask=function(t,e,n,i){var r=this,o=e.overallTask=e.overallTask||Bf({reset:py}),a=(o.context={ecModel:n,api:i,overallReset:t.overallReset,scheduler:r},o.agentStubMap),s=o.agentStubMap=G(),e=t.seriesType,l=t.getTargetSeries,u=!0,h=!1;function c(t){var e=t.uid,e=s.set(e,a&&a.get(e)||(h=!0,Bf({reset:dy,onDirty:gy})));e.context={model:t,overallProgress:u},e.agent=o,e.__block=u,r._pipe(t,e)}It(!t.createOnAllSeries,""),e?n.eachRawSeriesByType(e,c):l?l(n,i).each(c):(u=!1,N(n.getSeries(),c)),h&&o.dirty()},cy.prototype._pipe=function(t,e){t=t.uid,t=this._pipelineMap.get(t);t.head||(t.head=e),t.tail&&t.tail.pipe(e),(t.tail=e).__idxInPipeline=t.count++,e.__pipeline=t},cy.wrapStageHandler=function(t,e){return(t=k(t)?{overallReset:t,seriesType:function(t){wy=null;try{t(by,Sy)}catch(t){}return wy}(t)}:t).uid=ip("stageHandler"),e&&(t.visualType=e),t};var hy=cy;function cy(t,e,n,i){this._stageTaskMap=G(),this.ecInstance=t,this.api=e,n=this._dataProcessorHandlers=n.slice(),i=this._visualHandlers=i.slice(),this._allHandlers=n.concat(i)}function py(t){t.overallReset(t.ecModel,t.api,t.payload)}function dy(t){return t.overallProgress&&fy}function fy(){this.agent.dirty(),this.getDownstream().dirty()}function gy(){this.agent&&this.agent.dirty()}function yy(t){return t.plan?t.plan(t.model,t.ecModel,t.api,t.payload):null}function my(t){t.useClearVisual&&t.data.clearAllVisual();t=t.resetDefines=zo(t.reset(t.model,t.ecModel,t.api,t.payload));return 1'+t.dom+""}),f.painter.getSvgRoot().innerHTML=g,i.connectedBackgroundColor&&f.painter.setBackgroundColor(i.connectedBackgroundColor),f.refreshImmediately(),f.painter.toDataURL()):(i.connectedBackgroundColor&&f.add(new qs({shape:{x:0,y:0,width:t,height:n},style:{fill:i.connectedBackgroundColor}})),N(p,function(t){t=new Bs({style:{x:t.left*e-l,y:t.top*e-u,image:t.dom}});f.add(t)}),f.refreshImmediately(),d.toDataURL("image/"+(i&&i.type||"png")))):this.getDataURL(i);this.id},c.prototype.convertToPixel=function(t,e){return Wm(this,"convertToPixel",t,e)},c.prototype.convertFromPixel=function(t,e){return Wm(this,"convertFromPixel",t,e)},c.prototype.containPixel=function(t,i){var r;if(!this._disposed)return N($o(this._model,t),function(t,n){0<=n.indexOf("Models")&&N(t,function(t){var e=t.coordinateSystem;e&&e.containPoint?r=r||!!e.containPoint(i):"seriesModels"===n&&(e=this._chartsMap[t.__viewId])&&e.containPoint&&(r=r||e.containPoint(i,t))},this)},this),!!r;this.id},c.prototype.getVisual=function(t,e){var t=$o(this._model,t,{defaultMainType:"series"}),n=t.seriesModel.getData(),t=t.hasOwnProperty("dataIndexInside")?t.dataIndexInside:t.hasOwnProperty("dataIndex")?n.indexOfRawIndex(t.dataIndex):null;if(null==t)return Py(n,e);var i=n,r=t,o=e;switch(o){case"color":return i.getItemVisual(r,"style")[i.getVisual("drawType")];case"opacity":return i.getItemVisual(r,"style").opacity;case"symbol":case"symbolSize":case"liftZ":return i.getItemVisual(r,o)}},c.prototype.getViewOfComponentModel=function(t){return this._componentsMap[t.__viewId]},c.prototype.getViewOfSeriesModel=function(t){return this._chartsMap[t.__viewId]},c.prototype._initEvents=function(){var t,n,i,s=this;N(h0,function(a){function t(t){var n,e,i,r=s.getModel(),o=t.target;"globalout"===a?n={}:o&&Ny(o,function(t){var e,t=pl(t);return t&&null!=t.dataIndex?(e=t.dataModel||r.getSeriesByIndex(t.seriesIndex),n=e&&e.getDataParams(t.dataIndex,t.dataType,o)||{},1):t.eventData&&(n=O({},t.eventData),1)},!0),n&&(e=n.componentType,i=n.componentIndex,"markLine"!==e&&"markPoint"!==e&&"markArea"!==e||(e="series",i=n.seriesIndex),i=(e=e&&null!=i&&r.getComponent(e,i))&&s["series"===e.mainType?"_chartsMap":"_componentsMap"][e.__viewId],n.event=t,n.type=a,s._$eventProcessor.eventInfo={targetEl:o,packedEvent:n,model:e,view:i},s.trigger(a,n))}t.zrEventfulCallAtLast=!0,s._zr.on(a,t,s)}),N(p0,function(t,e){s._messageCenter.on(e,function(t){this.trigger(e,t)},s)}),N(["selectchanged"],function(e){s._messageCenter.on(e,function(t){this.trigger(e,t)},s)}),t=this._messageCenter,i=(n=this)._api,t.on("selectchanged",function(t){var e=i.getModel();t.isFromClick?(Oy("map","selectchanged",n,e,t),Oy("pie","selectchanged",n,e,t)):"select"===t.fromAction?(Oy("map","selected",n,e,t),Oy("pie","selected",n,e,t)):"unselect"===t.fromAction&&(Oy("map","unselected",n,e,t),Oy("pie","unselected",n,e,t))})},c.prototype.isDisposed=function(){return this._disposed},c.prototype.clear=function(){this._disposed?this.id:this.setOption({series:[]},!0)},c.prototype.dispose=function(){var t,e,n;this._disposed?this.id:(this._disposed=!0,this.getDom()&&ea(this.getDom(),b0,""),e=(t=this)._api,n=t._model,N(t._componentsViews,function(t){t.dispose(n,e)}),N(t._chartsViews,function(t){t.dispose(n,e)}),t._zr.dispose(),t._dom=t._model=t._chartsMap=t._componentsMap=t._chartsViews=t._componentsViews=t._scheduler=t._api=t._zr=t._throttledZrFlush=t._theme=t._coordSysMgr=t._messageCenter=null,delete v0[t.id])},c.prototype.resize=function(t){if(!this[km])if(this._disposed)this.id;else{this._zr.resize(t);var e=this._model;if(this._loadingFX&&this._loadingFX.resize(),e){var e=e.resetOption("media"),n=t&&t.silent;this[Dm]&&(null==n&&(n=this[Dm].silent),e=!0,this[Dm]=null),this[km]=!0;try{e&&Fm(this),Gm.update.call(this,{type:"resize",animation:O({duration:0},t&&t.animation)})}catch(t){throw this[km]=!1,t}this[km]=!1,Ym.call(this,n),qm.call(this,n)}}},c.prototype.showLoading=function(t,e){this._disposed?this.id:(P(t)&&(e=t,t=""),t=t||"default",this.hideLoading(),m0[t]&&(t=m0[t](this._api,e),e=this._zr,this._loadingFX=t,e.add(t)))},c.prototype.hideLoading=function(){this._disposed?this.id:(this._loadingFX&&this._zr.remove(this._loadingFX),this._loadingFX=null)},c.prototype.makeActionFromEvent=function(t){var e=O({},t);return e.type=p0[t.type],e},c.prototype.dispatchAction=function(t,e){var n;this._disposed?this.id:(P(e)||(e={silent:!!e}),c0[t.type]&&this._model&&(this[km]?this._pendingActions.push(t):(n=e.silent,Xm.call(this,t,n),(t=e.flush)?this._zr.flush():!1!==t&&p.browser.weChat&&this._throttledZrFlush(),Ym.call(this,n),qm.call(this,n))))},c.prototype.updateLabelLayout=function(){Cm.trigger("series:layoutlabels",this._model,this._api,{updatedSeries:[]})},c.prototype.appendData=function(t){var e;this._disposed?this.id:(e=t.seriesIndex,this.getModel().getSeriesByIndex(e).appendData(t),this._scheduler.unfinished=!0,this.getZr().wakeUp())},c.internalField=(Fm=function(t){var e=t._scheduler;e.restorePipelines(t._model),e.prepareStageTasks(),Vm(t,!0),Vm(t,!1),e.plan()},Vm=function(t,r){for(var o=t._model,a=t._scheduler,s=r?t._componentsViews:t._chartsViews,l=r?t._componentsMap:t._chartsMap,u=t._zr,h=t._api,e=0;es.get("hoverLayerThreshold")&&!p.node&&!p.worker&&s.eachSeries(function(t){t.preventUsingHoverLayer||(t=i._chartsMap[t.__viewId]).__alive&&t.eachRendered(function(t){t.states.emphasis&&(t.states.emphasis.hoverLayer=!0)})}),Cm.trigger("series:afterupdate",t,e,n)},e0=function(t){t[Am]=!0,t.getZr().wakeUp()},n0=function(t){t[Am]&&(t.getZr().storage.traverse(function(t){$h(t)||a0(t)}),t[Am]=!1)},Jm=function(n){return u(t,e=Nd),t.prototype.getCoordinateSystems=function(){return n._coordSysMgr.getCoordinateSystems()},t.prototype.getComponentByElement=function(t){for(;t;){var e=t.__ecComponentInfo;if(null!=e)return n._model.getComponent(e.mainType,e.index);t=t.parent}},t.prototype.enterEmphasis=function(t,e){Wl(t,e),e0(n)},t.prototype.leaveEmphasis=function(t,e){Ul(t,e),e0(n)},t.prototype.enterBlur=function(t){Xl(t),e0(n)},t.prototype.leaveBlur=function(t){Yl(t),e0(n)},t.prototype.enterSelect=function(t){ql(t),e0(n)},t.prototype.leaveSelect=function(t){jl(t),e0(n)},t.prototype.getModel=function(){return n.getModel()},t.prototype.getViewOfComponentModel=function(t){return n.getViewOfComponentModel(t)},t.prototype.getViewOfSeriesModel=function(t){return n.getViewOfSeriesModel(t)},new t(n);function t(){return null!==e&&e.apply(this,arguments)||this}var e},void(t0=function(i){function r(t,e){for(var n=0;ne[1]&&(e[1]=t[1])},Mv.prototype.unionExtentFromData=function(t,e){this.unionExtent(t.getApproximateExtent(e))},Mv.prototype.getExtent=function(){return this._extent.slice()},Mv.prototype.setExtent=function(t,e){var n=this._extent;isNaN(t)||(n[0]=t),isNaN(e)||(n[1]=e)},Mv.prototype.isInExtentRange=function(t){return this._extent[0]<=t&&this._extent[1]>=t},Mv.prototype.isBlank=function(){return this._isBlank},Mv.prototype.setBlank=function(t){this._isBlank=t};var Sv=Mv;function Mv(t){this._setting=t||{},this._extent=[1/0,-1/0]}pa(Sv);var Tv=0,Cv=(Iv.createByAxisModel=function(t){var t=t.option,e=t.data,e=e&&B(e,kv);return new Iv({categories:e,needCollect:!e,deduplication:!1!==t.dedplication})},Iv.prototype.getOrdinal=function(t){return this._getOrCreateMap().get(t)},Iv.prototype.parseAndCollect=function(t){var e,n,i=this._needCollect;return V(t)||i?(i&&!this._deduplication?(n=this.categories.length,this.categories[n]=t):null==(n=(e=this._getOrCreateMap()).get(t))&&(i?(n=this.categories.length,this.categories[n]=t,e.set(t,n)):n=NaN),n):t},Iv.prototype._getOrCreateMap=function(){return this._map||(this._map=G(this.categories))},Iv);function Iv(t){this.categories=t.categories||[],this._needCollect=t.needCollect,this._deduplication=t.deduplication,this.uid=++Tv}function kv(t){return P(t)&&null!=t.value?t.value:t+""}function Dv(t){return"interval"===t.type||"log"===t.type}function Av(t,e,n,i){var r={},o=t[1]-t[0],o=r.interval=Lo(o/e,!0),e=(null!=n&&oi[1]&&(i[0]=i[1]),r}function Lv(t){var e=Math.pow(10,Ao(t)),t=t/e;return t?2===t?t=3:3===t?t=5:t*=2:t=1,wo(t*e)}function Pv(t){return bo(t)+2}function Ov(t,e,n){t[e]=Math.max(Math.min(t[e],n[1]),n[0])}function Nv(t,e){return t>=e[0]&&t<=e[1]}function Rv(t,e){return e[1]===e[0]?.5:(t-e[0])/(e[1]-e[0])}function Ev(t,e){return t*(e[1]-e[0])+e[0]}u(Fv,zv=Sv),Fv.prototype.parse=function(t){return null==t?NaN:V(t)?this._ordinalMeta.getOrdinal(t):Math.round(t)},Fv.prototype.contain=function(t){return Nv(t=this.parse(t),this._extent)&&null!=this._ordinalMeta.categories[t]},Fv.prototype.normalize=function(t){return Rv(t=this._getTickNumber(this.parse(t)),this._extent)},Fv.prototype.scale=function(t){return t=Math.round(Ev(t,this._extent)),this.getRawOrdinalNumber(t)},Fv.prototype.getTicks=function(){for(var t=[],e=this._extent,n=e[0];n<=e[1];)t.push({value:n}),n++;return t},Fv.prototype.getMinorTicks=function(t){},Fv.prototype.setSortInfo=function(t){if(null==t)this._ordinalNumbersByTick=this._ticksByOrdinalNumber=null;else{for(var e=t.ordinalNumbers,n=this._ordinalNumbersByTick=[],i=this._ticksByOrdinalNumber=[],r=0,o=this._ordinalMeta.categories.length,a=Math.min(o,e.length);r=t},Fv.prototype.getOrdinalMeta=function(){return this._ordinalMeta},Fv.prototype.calcNiceTicks=function(){},Fv.prototype.calcNiceExtent=function(){},Fv.type="ordinal";var zv,Bv=Fv;function Fv(t){var t=zv.call(this,t)||this,e=(t.type="ordinal",t.getSetting("ordinalMeta"));return F(e=e||new Cv({}))&&(e=new Cv({categories:B(e,function(t){return P(t)?t.value:t})})),t._ordinalMeta=e,t._extent=t.getSetting("extent")||[0,e.categories.length-1],t}Sv.registerClass(Bv);var Vv,Hv=wo,Gv=(u(Wv,Vv=Sv),Wv.prototype.parse=function(t){return t},Wv.prototype.contain=function(t){return Nv(t,this._extent)},Wv.prototype.normalize=function(t){return Rv(t,this._extent)},Wv.prototype.scale=function(t){return Ev(t,this._extent)},Wv.prototype.setExtent=function(t,e){var n=this._extent;isNaN(t)||(n[0]=parseFloat(t)),isNaN(e)||(n[1]=parseFloat(e))},Wv.prototype.unionExtent=function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1]),this.setExtent(e[0],e[1])},Wv.prototype.getInterval=function(){return this._interval},Wv.prototype.setInterval=function(t){this._interval=t,this._niceExtent=this._extent.slice(),this._intervalPrecision=Pv(t)},Wv.prototype.getTicks=function(t){var e=this._interval,n=this._extent,i=this._niceExtent,r=this._intervalPrecision,o=[];if(e){n[0]s&&o.push(t?{value:Hv(s+e,r)}:{value:n[1]})}return o},Wv.prototype.getMinorTicks=function(t){for(var e=this.getTicks(!0),n=[],i=this.getExtent(),r=1;ri[0]&&h=M[0]&&d<=M[1]&&a++)}u=(M[1]-M[0])/b;if(1.5*u=M[0]&&t.value<=M[1]&&!t.notAdd})}),function(t){return 0n&&(this._approxInterval=n),t_.length),t=Math.min(function(t,e,n,i){for(;n>>1;t[r][1]>1^-(1&s),l=(l=t.charCodeAt(a+1)-64)>>1^-(1&l);i.push([(r=s+=r)/n,(o=l+=o)/n])}return i}function Y_(t,o){var e,n,r;return B(ct((t=(e=t).UTF8Encoding?(null==(r=(n=e).UTF8Scale)&&(r=1024),N(n.features,function(t){var e=t.geometry,n=e.encodeOffsets,i=e.coordinates;if(n)switch(e.type){case"LineString":e.coordinates=X_(i,n,r);break;case"Polygon":case"MultiLineString":U_(i,n,r);break;case"MultiPolygon":N(i,function(t,e){return U_(t,n[e],r)})}}),n.UTF8Encoding=!1,n):e).features,function(t){return t.geometry&&t.properties&&0l&&(l=s[h],u=h);++o[u],s[u]=0,++a}return B(o,function(t){return t/i})}(t,n)[e]||0},getPixelPrecision:Mo,getPrecision:bo,getPrecisionSafe:So,isNumeric:Oo,isRadianAroundZero:Co,linearMap:_o,nice:Lo,numericToNumber:Po,parseDate:ko,quantile:function(t,e){var e=(t.length-1)*e+1,n=Math.floor(e),i=+t[n-1];return(e=e-n)?i+e*(t[n]-i):i},quantity:Do,quantityExponent:Ao,reformIntervals:function(t){t.sort(function(t,e){return function t(e,n,i){return e.interval[i]':'':{renderMode:r,content:"{"+(t.markerId||"markerX")+"|} ",style:"subItem"===i?{width:4,height:4,borderRadius:2,backgroundColor:n}:{width:10,height:10,borderRadius:5,backgroundColor:n}}:""},normalizeCssArray:Vp,toCamelCase:function(t,e){return t=(t||"").toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()}),t=e?t&&t.charAt(0).toUpperCase()+t.slice(1):t},truncateText:ba}),Ly=Object.freeze({__proto__:null,bind:dt,clone:_,curry:ft,defaults:z,each:N,extend:O,filter:ct,indexOf:I,inherits:st,isArray:F,isFunction:k,isObject:P,isString:V,map:B,merge:d,reduce:ht}),q_=Zo();function j_(t){return"category"===t.type?(r=(e=t).getLabelModel(),o=K_(e,r),!r.get("show")||e.scale.isBlank()?{labels:[],labelCategoryInterval:o.labelCategoryInterval}:o):(r=(n=t).scale.getTicks(),i=w_(n),{labels:B(r,function(t,e){return{level:t.level,formattedLabel:i(t,e),rawLabel:n.scale.getLabel(t),tickValue:t.value}})});var n,i,e,r,o}function Z_(t,e){var n,i,r,o,a,s;return"category"===t.type?(e=e,o=$_(n=t,"ticks"),a=S_(e),(s=Q_(o,a))||(e.get("show")&&!n.scale.isBlank()||(i=[]),i=k(a)?e1(n,a,!0):"auto"===a?(s=K_(n,n.getLabelModel()),r=s.labelCategoryInterval,B(s.labels,function(t){return t.tickValue})):t1(n,r=a,!0),J_(o,a,{ticks:i,tickCategoryInterval:r}))):{ticks:B(t.scale.getTicks(),function(t){return t.value})}}function K_(t,e){var n,i=$_(t,"labels"),e=S_(e),r=Q_(i,e);return r||J_(i,e,{labels:k(e)?e1(t,e):t1(t,n="auto"===e?null!=(i=q_(r=t).autoInterval)?i:q_(r).autoInterval=r.calculateCategoryInterval():e),labelCategoryInterval:n})}function $_(t,e){return q_(t)[e]||(q_(t)[e]=[])}function Q_(t,e){for(var n=0;nl[1],h(n[0].coord,l[0])&&(t?n[0].coord=l[0]:n.shift()),t&&h(l[0],n[0].coord)&&n.unshift({coord:l[0]}),h(l[1],i.coord)&&(t?i.coord=l[1]:n.pop()),t)&&h(i.coord,l[1])&&n.push({coord:l[1]}),u},i1.prototype.getMinorTicksCoords=function(){var t;return"ordinal"===this.scale.type?[]:(t=this.model.getModel("minorTick").get("splitNumber"),B(this.scale.getMinorTicks(t=0=u}}for(var o,a=this.__startIndex;ar[0]){for(l=0;lt);l++);s=i[r[l]]}r.splice(l+1,0,t),(i[t]=e).virtual||(s?(n=s.dom).nextSibling?a.insertBefore(e.dom,n.nextSibling):a.appendChild(e.dom):a.firstChild?a.insertBefore(e.dom,a.firstChild):a.appendChild(e.dom)),e.painter||(e.painter=this)}},m.prototype.eachLayer=function(t,e){for(var n=this._zlevelList,i=0;ie[u-1].coord&&(e.reverse(),h.reverse()),function(t,e){var n,i,r=[],o=t.length;function a(t,e,n){var i=t.coord;return{coord:n,color:wi((n-i)/(e.coord-i),[t.color,e.color])}}for(var s=0;si)return;return 1}(a,e))return r=e.mapDimension(a.dim),o={},N(a.getViewLabels(),function(t){t=a.scale.getRawOrdinalNumber(t.tickValue);o[t]=1}),function(t){return!o.hasOwnProperty(e.get(r,t))}}}function Ox(t){for(var e,n,i=t.length/2;0e&&(e=t[n]);return isFinite(e)?e:NaN},min:function(t){for(var e=1/0,n=0;nh[1]?-1:1,o=["start"===c?h[0]-o*u:"end"===c?h[1]+o*u:(h[0]+h[1])/2,cw(c)?t.labelOffset+l*u:0],null!=(u=e.get("nameRotate"))&&(u=u*ow/180),cw(c)?a=aw.innerTextLayout(t.rotation,null!=u?u:t.rotation,l):(a=function(t,e,n,i){var r,n=To(n-t),t=i[0]>i[1],i="start"===e&&!t||"start"!==e&&t;e=Co(n-ow/2)?(r=i?"bottom":"top","center"):Co(n-1.5*ow)?(r=i?"top":"bottom","center"):(r="middle",n<1.5*ow&&ow/2s[0]&&isFinite(c)&&isFinite(s[0]);)h=Lv(h),c=s[1]-h*a;else{u=(h=ae[1]&&e.reverse(),e},Gw.prototype.pointToData=function(t,e){return this.coordToData(this.toLocalCoord(t["x"===this.dim?0:1]),e)},Gw.prototype.setCategorySortInfo=function(t){if("category"!==this.type)return!1;this.model.option.categorySortInfo=t,this.scale.setSortInfo(t)};var Vw,Hw=Gw;function Gw(t,e,n,i,r){t=Vw.call(this,t,e,n)||this;return t.index=0,t.type=i||"value",t.position=r||"bottom",t}function Ww(t){return"cartesian2d"===t.get("coordinateSystem")}function Uw(i){var r={xAxisModel:null,yAxisModel:null};return N(r,function(t,e){var n=e.replace(/Model$/,""),n=i.getReferringComponents(n,Jo).models[0];r[e]=n}),r}Yw.prototype.getRect=function(){return this._rect},Yw.prototype.update=function(t,e){var n=this._axesMap;function i(t){var e,n=R(t),i=n.length;if(i){for(var r=[],o=i-1;0<=o;o--){var a=t[+n[o]],s=a.model,l=a.scale;Dv(l)&&s.get("alignTicks")&&null==s.get("interval")?r.push(a):(__(l,s),Dv(l)&&(e=a))}r.length&&(e||__((e=r.pop()).scale,e.model),N(r,function(t){ww(t.scale,t.model,e.scale)}))}}this._updateScale(t,this.model),i(n.x),i(n.y);var r={};N(n.x,function(t){jw(n,"y",t,r)}),N(n.y,function(t){jw(n,"x",t,r)}),this.resize(this.model,e)},Yw.prototype.resize=function(t,e,n){var i=t.getBoxLayoutParams(),n=!n&&t.get("containLabel"),a=jp(i,{width:e.getWidth(),height:e.getHeight()}),r=(this._rect=a,this._axesList);function o(){N(r,function(t){var e,n,i=t.isHorizontal(),r=i?[0,a.width]:[0,a.height],o=t.inverse?1:0;t.setExtent(r[o],r[1-o]),r=t,e=i?a.x:a.y,o=r.getExtent(),n=o[0]+o[1],r.toGlobalCoord="x"===r.dim?function(t){return t+e}:function(t){return n-t+e},r.toLocalCoord="x"===r.dim?function(t){return t-e}:function(t){return n-t+e}})}o(),n&&(N(r,function(t){var e,n,i;t.model.get(["axisLabel","inside"])||(e=b_(t))&&(n=t.isHorizontal()?"height":"width",i=t.model.get(["axisLabel","margin"]),a[n]-=e[n]+i,"top"===t.position?a.y+=e.height+i:"left"===t.position&&(a.x+=e.width+i))}),o()),N(this._coordsList,function(t){t.calcAffineTransform()})},Yw.prototype.getAxis=function(t,e){t=this._axesMap[t];if(null!=t)return t[e||0]},Yw.prototype.getAxes=function(){return this._axesList.slice()},Yw.prototype.getCartesian=function(t,e){if(null!=t&&null!=e)return this._coordsMap["x"+t+"y"+e];P(t)&&(e=t.yAxisIndex,t=t.xAxisIndex);for(var n=0,i=this._coordsList;nu[1]&&u.reverse(),(s=null==s||s>u[1]?u[1]:s)":"gt",">=":"gte","=":"eq","!=":"ne","<>":"ne"},cS=(pS.prototype.evaluate=function(t){var e=typeof t;return V(e)?this._condVal.test(t):!!H(e)&&this._condVal.test(t+"")},pS);function pS(t){null==(this._condVal=V(t)?new RegExp(t):wt(t)?t:null)&&f("")}fS.prototype.evaluate=function(){return this.value};var dS=fS;function fS(){}yS.prototype.evaluate=function(){for(var t=this.children,e=0;e"}(i,r)+("style"!==i?xe(e):e||"")+(n?o+B(n,t).join(o)+o:"")+""}(t)}function KS(t){return{zrId:t,shadowCache:{},patternCache:{},gradientCache:{},clipPathCache:{},defs:{},cssNodes:{},cssAnims:{},cssStyleCache:{},cssAnimIdx:0,shadowIdx:0,gradientIdx:0,patternIdx:0,clipPathIdx:0}}function $S(t,e,n,i){return jS("svg","root",{width:t,height:e,xmlns:GS,"xmlns:xlink":WS,version:"1.1",baseProfile:"full",viewBox:!!i&&"0 0 "+t+" "+e},n)}var QS=0;var JS={cubicIn:"0.32,0,0.67,0",cubicOut:"0.33,1,0.68,1",cubicInOut:"0.65,0,0.35,1",quadraticIn:"0.11,0,0.5,0",quadraticOut:"0.5,1,0.89,1",quadraticInOut:"0.45,0,0.55,1",quarticIn:"0.5,0,0.75,0",quarticOut:"0.25,1,0.5,1",quarticInOut:"0.76,0,0.24,1",quinticIn:"0.64,0,0.78,0",quinticOut:"0.22,1,0.36,1",quinticInOut:"0.83,0,0.17,1",sinusoidalIn:"0.12,0,0.39,0",sinusoidalOut:"0.61,1,0.88,1",sinusoidalInOut:"0.37,0,0.63,1",exponentialIn:"0.7,0,0.84,0",exponentialOut:"0.16,1,0.3,1",exponentialInOut:"0.87,0,0.13,1",circularIn:"0.55,0,1,0.45",circularOut:"0,0.55,0.45,1",circularInOut:"0.85,0,0.15,1"},tM="transform-origin";var eM={fill:"fill",opacity:"opacity",lineWidth:"stroke-width",lineDashOffset:"stroke-dashoffset"};function nM(t,e){var n=e.zrId+"-ani-"+e.cssAnimIdx++;return e.cssAnims[n]=t,n}function iM(t){return V(t)?JS[t]?"cubic-bezier("+JS[t]+")":Kn(t)?t:"":""}function rM(D,A,L,P){var t=D.animators,e=t.length,n=[];if(D instanceof Dh){if(r=function(t,e,u){var h,c,t=t.shape.paths,p={};if(N(t,function(t){var e=KS(u.zrId),t=(e.animation=!0,rM(t,{},e,!0),e.cssAnims),n=e.cssNodes,e=R(t),i=e.length;if(i){var r,o,a=t[c=e[i-1]];for(r in a){var s=a[r];p[r]=p[r]||{d:""},p[r].d+=s.d||""}for(o in n){var l=n[o].animation;0<=l.indexOf(c)&&(h=l)}}}),h)return e.d=!1,t=nM(p,u),h.replace(c,t)}(D,A,L))n.push(r);else if(!e)return}else if(!e)return;for(var i,r,o,a={},s=0;s"].join(o):"")&&(e=jS("style","stl",{},[],c),h.push(e)),$S(i,l,h,t.useViewBox)},HM.prototype.renderToString=function(t){return ZS(this.renderToVNode({animation:E((t=t||{}).cssAnimation,!0),emphasis:E(t.cssEmphasis,!0),willUpdate:!1,compress:!0,useViewBox:E(t.useViewBox,!0)}),{newline:!0})},HM.prototype.setBackgroundColor=function(t){this._backgroundColor=t},HM.prototype.getSvgRoot=function(){return this._mainVNode&&this._mainVNode.elm},HM.prototype._paintList=function(t,e,n){for(var i,r,o,a,s,l,u,h=t.length,c=[],p=0,d=0,f=0;f= 0) && (a <= 255) ? a/255 : 1); + return 'rgba(' + values.join(',') + ')'; + }, + + getDump: function(){ + var i, + xml, + rect, + fg = this.foreground, + bg = this.background, + stroke = this.size * 0.005; + + xml = "" + + ""; + + for (i = 0; i < this.rectangles.length; i++) { + rect = this.rectangles[i]; + if (rect.color == bg) continue; + xml += ""; + } + xml += "" + + return xml; + }, + + getBase64: function(){ + if ('function' === typeof btoa) { + return btoa(this.getDump()); + } else if (Buffer) { + return new Buffer(this.getDump(), 'binary').toString('base64'); + } else { + throw 'Cannot generate base64 output'; + } + } + }; + + if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = Identicon; + } else { + window.Identicon = Identicon; + } +})(); diff --git a/nonebot_plugin_tetris_stats/templates/static/bind/error.svg b/nonebot_plugin_tetris_stats/templates/static/bind/error.svg new file mode 100644 index 0000000..2253b60 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/bind/error.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/bind/success.svg b/nonebot_plugin_tetris_stats/templates/static/bind/success.svg new file mode 100644 index 0000000..86e1f4f --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/bind/success.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/bind/unknown.svg b/nonebot_plugin_tetris_stats/templates/static/bind/unknown.svg new file mode 100644 index 0000000..7f96fc6 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/bind/unknown.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/bind/unlink.svg b/nonebot_plugin_tetris_stats/templates/static/bind/unlink.svg new file mode 100644 index 0000000..1732f37 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/bind/unlink.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/bind/unverified.svg b/nonebot_plugin_tetris_stats/templates/static/bind/unverified.svg new file mode 100644 index 0000000..aac997e --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/bind/unverified.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/data/40L.svg b/nonebot_plugin_tetris_stats/templates/static/data/40L.svg new file mode 100644 index 0000000..f330d1d --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/data/40L.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/data/ADPM.svg b/nonebot_plugin_tetris_stats/templates/static/data/ADPM.svg new file mode 100644 index 0000000..21723ee --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/data/ADPM.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/data/APM.svg b/nonebot_plugin_tetris_stats/templates/static/data/APM.svg new file mode 100644 index 0000000..e29694f --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/data/APM.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/data/Blitz.svg b/nonebot_plugin_tetris_stats/templates/static/data/Blitz.svg new file mode 100644 index 0000000..2f8092d --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/data/Blitz.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/data/LPM.svg b/nonebot_plugin_tetris_stats/templates/static/data/LPM.svg new file mode 100644 index 0000000..2cdb34b --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/data/LPM.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/data/point.svg b/nonebot_plugin_tetris_stats/templates/static/data/point.svg new file mode 100644 index 0000000..1482b4c --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/data/point.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/fonts/26FGalaxySans/26FGalaxySans-ObliqueVF.woff2 b/nonebot_plugin_tetris_stats/templates/static/fonts/26FGalaxySans/26FGalaxySans-ObliqueVF.woff2 new file mode 100644 index 0000000..7dc5113 Binary files /dev/null and b/nonebot_plugin_tetris_stats/templates/static/fonts/26FGalaxySans/26FGalaxySans-ObliqueVF.woff2 differ diff --git a/nonebot_plugin_tetris_stats/templates/static/fonts/26FGalaxySans/License/OFL.txt b/nonebot_plugin_tetris_stats/templates/static/fonts/26FGalaxySans/License/OFL.txt new file mode 100644 index 0000000..979037e --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/fonts/26FGalaxySans/License/OFL.txt @@ -0,0 +1,92 @@ +(C) Copyright 2019–2022 26F Studio. + +This Font Software is licensed under the SIL Open Font License, +Version 1.1. This license is copied below, and is also available at +https://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/nonebot_plugin_tetris_stats/templates/static/fonts/CabinetGrotesk/CabinetGrotesk-Variable.woff2 b/nonebot_plugin_tetris_stats/templates/static/fonts/CabinetGrotesk/CabinetGrotesk-Variable.woff2 new file mode 100644 index 0000000..5462835 Binary files /dev/null and b/nonebot_plugin_tetris_stats/templates/static/fonts/CabinetGrotesk/CabinetGrotesk-Variable.woff2 differ diff --git a/nonebot_plugin_tetris_stats/templates/static/fonts/CabinetGrotesk/License/FFL.txt b/nonebot_plugin_tetris_stats/templates/static/fonts/CabinetGrotesk/License/FFL.txt new file mode 100644 index 0000000..4200744 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/fonts/CabinetGrotesk/License/FFL.txt @@ -0,0 +1,58 @@ +Fontshare EULA + + +---—---------------------------------—------------------------------ +Free Font - End User License Agreement (FF EULA) +---—---------------------------------—------------------------------ +Notice to User +Indian Type Foundry designs, produces and distributes font software as digital fonts to end users worldwide. In addition to commercial fonts that are available for a fee, ITF also offers several fonts which can be used free of charge. The free fonts are distributed through a dedicated platform called www.fontshare.com (“Fontshare”) to end users worldwide. These free fonts are subject to this legally binding EULA between the Indian Type Foundry (“Indian Type Foundry” or “Licensor”) and you (“Licensee”).  +You acknowledge that the Font Software and designs embodied therein are protected by the copyright, other intellectual property rights and industrial property rights and by international treaties. They are and remain at all times the intellectual property of the Indian Type Foundry. +In addition to direct download, Fontshare also offers these free fonts via Fonthsare API using a code. In this case, the Font Software is delivered directly from the servers used by Indian Type Foundry to the Licensee's website, without the Licensee having to download the Font Software. +By downloading, accessing the API, installing, storing, copying or using one of any Font Software, you agree to the following terms.  + +Definitions +“Font Software” refers to the set of computer files or programs released under this license that instructs your computer to display and/or print each letters, characters, typographic designs, ornament and so forth. Font Software includes all bitmap and vector representations of fonts and typographic representations and embellishments created by or derived from the Font Software.  +“Original Version” refers to the Font Software as distributed by the Indian Type Foundry as the copyright holder.  +“Derivative Work” refers to the pictorial representation of the font created by the Font Software, including typographic characters such as letters, numerals, ornaments, symbols, or punctuation and special characters. + +01. Grant of License +You are hereby granted a non-exclusive, non-assignable, non-transferrable, terminable license to access, download and use the Font Software for your personal or commercial use for an unlimited period of time for free of charge.  +You may use the font Software in any media (including Print, Web, Mobile, Digital, Apps, ePub, Broadcasting and OEM) at any scale, at any location worldwide.  +You may use the Font Software to create logos and other graphic elements, images on any surface, vector files or other scalable drawings and static images.  +You may use the Font Software on any number of devices (computer, tablet, phone). The number of output devices (Printers) is not restricted.  +You may make only such reasonable number of back-up copies suitable to your permitted use.  +You may but are not required to identify Indian Type Foundry Fonts in your work credits.  + +02. Limitations of usage +You may not modify, edit, adapt, translate, reverse engineer, decompile or disassemble, alter or otherwise copy the Font Software or the designs embodied therein in whole or in part, without the prior written consent of the Licensor.  +The Fonts may not - beyond the permitted copies and the uses defined herein - be distributed, duplicated, loaned, resold or licensed in any way, whether by lending, donating or give otherwise to a person or entity. This includes the distribution of the Fonts by e-mail, on USB sticks, CD-ROMs, or other media, uploading them in a public server or making the fonts available on peer-to-peer networks. A passing on to external designers or service providers (design agencies, repro studios, printers, etc.) is also not permitted.  +You are not allowed to transmit the Font Software over the Internet in font serving or for font replacement by means of technologies such as but not limited to EOT, Cufon, sIFR or similar technologies that may be developed in the future without the prior written consent of the Licensor.  + +03. Embedding +You may embed the Font Software in PDF and other digital documents provided that is done in a secured, read-only mode. It must be ensured beyond doubt that the recipient cannot use the Font Software to edit or to create new documents. The design data (PDFs) created in this way and under these created design data (PDFs) may be distributed in any number.  +The extraction of the Font Software in whole or in part is prohibited.  + +04. Third party use, Commercial print service provider +You may include the Font Software in a non-editable electronic document solely for printing and display purposes and provide that electronic document to the commercial print service provider for the purpose of printing. If the print service needs to install the fonts, they too need to download the Font Software from the Licensor's website. + +05. Derivative Work +You are allowed to make derivative works as far as you use them for your personal or commercial use. However, you cannot modify, make changes or reverse engineer the original font software provided to you. Any derivative works are the exclusive property of the Licensor and shall be subject to the terms and conditions of this EULA. Derivative works may not be sub-licensed, sold, leased, rented, loaned, or given away without the express written permission of the Licensor.  + +06. Warranty and Liability +BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, INDIAN TYPE FOUNDRY MAKES NO WARRANTIES, EXPRESS OR IMPLIED AS TO THE MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR OTHERWISE. THE FONT SOFTWARE WAS NOT MANUFACTURED FOR USE IN MANUFACTURING CONTROL DEVICES OR NAVIGATION DEVICES OR IN CIRCUMSTANCES THAT COULD RESULT IN ENVIRONMENTAL DAMAGE OR PERSONAL INJURY. WITHOUT LIMITING THE FOREGOING, INDIAN TYPE FOUNDRY SHALL IN NO EVENT BE LIABLE TO THE LICENSED USER OR ANY OTHER THIRD PARTY FOR ANY DIRECT, CONSEQUENTIAL OR INCIDENTAL DAMAGES, INCLUDING DAMAGES FROM LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION NOR FOR LOST PROFITS OR SAVINGS ARISING OUT OF THE USE OR INABILITY TO USE THE PRODUCT EVEN IF NOTIFIED IN ADVANCE, UNDER NO CIRCUMSTANCES SHALL INDIAN TYPE FOUNDRY’S LIABILITY EXCEED THE REPLACEMENT COST OF THE SOFTWARE.  +IF LICENSEE CHOOSES TO ACCESS THE FONT SOFTWARE THROUGH A CODE (API), IT MAY HAVE A DIRECT IMPACT ON LICENSEE'S WEBSITE OR APPLICATIONS. INDIAN TYPE FOUNDRY IS NOT RESPONSIBLE OR LIABLE FOR ANY INTERRUPTION, MALFUNCTION, DOWNTIME OR OTHER FAILURE OF THE WEBSITE OR ITS API. + +07. Updates, Maintenance and Support Services +Licensor will not provide you with any support services for the Software under this Agreement. + +08. Termination  +Any breach of the terms of this agreement shall be a cause for termination, provided that such breach is notified in writing to the Licensee by the Licensor and the Licensee failed to rectify the breach within 30 days of the receipt of such notification.  +In the event of termination and without limitation of any remedies under law or equity, you must delete the Font Software and all copies thereof. Proof of this must be provided upon request of the Licensor.   +We reserve the right to claim damages for the violation of the conditions.  + +09. Final Provisions +If individual provisions of this agreement are or become invalid, the validity of the remaining provisions shall remain unaffected. Invalid provisions shall be replaced by mutual agreement by such provisions that are suitable to achieve the desired economic purpose, taking into account the interests of both parties. The same shall apply mutatis mutandis to the filling of any gaps which may arise in this agreement. +This contract is subject to laws of the Republic of India. Place of performance and exclusive place of jurisdiction for all disputes between the parties arising out of or in connection with this contract is, as far as legally permissible, Ahmedabad, India. +-  +Last Updated on 22 March 2021 +Copyright 2021 Indian Type Foundry. All rights reserved.  \ No newline at end of file diff --git a/nonebot_plugin_tetris_stats/templates/static/fonts/SourceHanSans/License/LICENSE.txt b/nonebot_plugin_tetris_stats/templates/static/fonts/SourceHanSans/License/LICENSE.txt new file mode 100644 index 0000000..ddf7b7e --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/fonts/SourceHanSans/License/LICENSE.txt @@ -0,0 +1,96 @@ +Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font +Name 'Source'. Source is a trademark of Adobe in the United States +and/or other countries. + +This Font Software is licensed under the SIL Open Font License, +Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font +creation efforts of academic and linguistic communities, and to +provide a free and open framework in which fonts may be shared and +improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply to +any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software +components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, +deleting, or substituting -- in part or in whole -- any of the +components of the Original Version, by changing formats or by porting +the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, +modify, redistribute, and sell modified and unmodified copies of the +Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in +Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the +corresponding Copyright Holder. This restriction only applies to the +primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created using +the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/nonebot_plugin_tetris_stats/templates/static/fonts/SourceHanSans/SourceHanSansSC-VF.otf.woff2 b/nonebot_plugin_tetris_stats/templates/static/fonts/SourceHanSans/SourceHanSansSC-VF.otf.woff2 new file mode 100644 index 0000000..3a492a7 Binary files /dev/null and b/nonebot_plugin_tetris_stats/templates/static/fonts/SourceHanSans/SourceHanSansSC-VF.otf.woff2 differ diff --git a/nonebot_plugin_tetris_stats/templates/static/logo/TETR.IO.svg b/nonebot_plugin_tetris_stats/templates/static/logo/TETR.IO.svg new file mode 100644 index 0000000..3b0b631 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/logo/TETR.IO.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/logo/logo.svg b/nonebot_plugin_tetris_stats/templates/static/logo/logo.svg new file mode 100644 index 0000000..aef6fe1 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/logo/logo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/logo/top.ico b/nonebot_plugin_tetris_stats/templates/static/logo/top.ico new file mode 100644 index 0000000..e7a79a8 Binary files /dev/null and b/nonebot_plugin_tetris_stats/templates/static/logo/top.ico differ diff --git a/nonebot_plugin_tetris_stats/templates/static/logo/tos.ico b/nonebot_plugin_tetris_stats/templates/static/logo/tos.ico new file mode 100644 index 0000000..9f53edb Binary files /dev/null and b/nonebot_plugin_tetris_stats/templates/static/logo/tos.ico differ diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/a+.svg b/nonebot_plugin_tetris_stats/templates/static/rank/a+.svg new file mode 100644 index 0000000..55d7c23 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/a+.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/a-.svg b/nonebot_plugin_tetris_stats/templates/static/rank/a-.svg new file mode 100644 index 0000000..bf77da5 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/a-.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/a.svg b/nonebot_plugin_tetris_stats/templates/static/rank/a.svg new file mode 100644 index 0000000..3491dcc --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/a.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/b+.svg b/nonebot_plugin_tetris_stats/templates/static/rank/b+.svg new file mode 100644 index 0000000..5b513bf --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/b+.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/b-.svg b/nonebot_plugin_tetris_stats/templates/static/rank/b-.svg new file mode 100644 index 0000000..4d30ae1 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/b-.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/b.svg b/nonebot_plugin_tetris_stats/templates/static/rank/b.svg new file mode 100644 index 0000000..2685b11 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/b.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/c+.svg b/nonebot_plugin_tetris_stats/templates/static/rank/c+.svg new file mode 100644 index 0000000..615693c --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/c+.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/c-.svg b/nonebot_plugin_tetris_stats/templates/static/rank/c-.svg new file mode 100644 index 0000000..a308e87 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/c-.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/c.svg b/nonebot_plugin_tetris_stats/templates/static/rank/c.svg new file mode 100644 index 0000000..af12a6b --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/c.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/d+.svg b/nonebot_plugin_tetris_stats/templates/static/rank/d+.svg new file mode 100644 index 0000000..99719a5 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/d+.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/d.svg b/nonebot_plugin_tetris_stats/templates/static/rank/d.svg new file mode 100644 index 0000000..022638e --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/d.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/s+.svg b/nonebot_plugin_tetris_stats/templates/static/rank/s+.svg new file mode 100644 index 0000000..026a479 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/s+.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/s-.svg b/nonebot_plugin_tetris_stats/templates/static/rank/s-.svg new file mode 100644 index 0000000..ebb5578 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/s-.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/s.svg b/nonebot_plugin_tetris_stats/templates/static/rank/s.svg new file mode 100644 index 0000000..72a8acc --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/s.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/ss.svg b/nonebot_plugin_tetris_stats/templates/static/rank/ss.svg new file mode 100644 index 0000000..84f889b --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/ss.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/u.svg b/nonebot_plugin_tetris_stats/templates/static/rank/u.svg new file mode 100644 index 0000000..2d65c94 --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/u.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/x.svg b/nonebot_plugin_tetris_stats/templates/static/rank/x.svg new file mode 100644 index 0000000..c49255e --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/x.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/templates/static/rank/z.svg b/nonebot_plugin_tetris_stats/templates/static/rank/z.svg new file mode 100644 index 0000000..31b60df --- /dev/null +++ b/nonebot_plugin_tetris_stats/templates/static/rank/z.svg @@ -0,0 +1,3 @@ + + + diff --git a/nonebot_plugin_tetris_stats/utils/avatar.py b/nonebot_plugin_tetris_stats/utils/avatar.py new file mode 100644 index 0000000..1b992f4 --- /dev/null +++ b/nonebot_plugin_tetris_stats/utils/avatar.py @@ -0,0 +1,81 @@ +from base64 import b64decode, b64encode +from io import BytesIO +from typing import Literal, overload + +from nonebot_plugin_userinfo import UserInfo # type: ignore[import-untyped] +from PIL import Image + +from ..templates import path +from .browser import BrowserManager + + +@overload +async def get_avatar(user: UserInfo, scheme: Literal['Data URI'], default: str | None) -> str: + """获取用户头像的指定格式 + + Args: + user (UserInfo): 要获取的用户 + scheme (Literal['Data URI']): 格式 + default (str | None): 获取不到时的默认值 + + Raises: + TypeError: Can't get avatar: 当获取不到头像并且没有设置默认值时抛出 + TypeError: Can't get avatar format: 当获取到的头像无法识别格式时抛出 + + Returns: + str: Data URI 格式的头像 + """ + + +@overload +async def get_avatar(user: UserInfo, scheme: Literal['bytes'], default: str | None) -> bytes: + """获取用户头像的指定格式 + + Args: + user (UserInfo): 要获取的用户 + scheme (Literal['bytes']): 格式 + default (str | None): 获取不到时的默认值 + + Returns: + bytes: bytes 格式的头像 + """ + + +async def get_avatar(user: UserInfo, scheme: Literal['Data URI', 'bytes'], default: str | None) -> str | bytes: + if user.user_avatar is None: + if default is None: + raise TypeError("Can't get avatar") + return default + bot_avatar = await user.user_avatar.get_image() + if scheme == 'Data URI': + avatar_format = Image.open(BytesIO(bot_avatar)).format + if avatar_format is None: + raise TypeError("Can't get avatar format") + return f'data:{Image.MIME[avatar_format]};base64,{b64encode(bot_avatar).decode()}' + return bot_avatar + + +async def generate_identicon(hash: str) -> bytes: # noqa: A002 + """使用 identicon 生成头像 + + Args: + hash (str): 提交给 identicon 的 hash 值 + + Returns: + bytes: identicon 生成的 svg 的二进制数据 + """ + browser = await BrowserManager.get_browser() + async with await browser.new_page() as page: + await page.add_script_tag(path=path / 'js/identicon.js') + return b64decode( + await page.evaluate(rf""" + new Identicon('{hash}', {{ + background: [0x08, 0x0a, 0x06, 255], + margin: 0.15, + size: 300, + brightness: 0.48, + saturation: 0.65, + format: 'svg', + }}).toString(); + """) + ) diff --git a/nonebot_plugin_tetris_stats/utils/host.py b/nonebot_plugin_tetris_stats/utils/host.py new file mode 100644 index 0000000..548612f --- /dev/null +++ b/nonebot_plugin_tetris_stats/utils/host.py @@ -0,0 +1,82 @@ +from hashlib import sha256 +from ipaddress import IPv4Address, IPv6Address +from typing import ClassVar + +from aiofiles import open +from fastapi import FastAPI, Query, Response, status +from fastapi.responses import FileResponse, HTMLResponse +from fastapi.staticfiles import StaticFiles +from nonebot import get_app, get_driver +from nonebot.log import logger +from nonebot_plugin_localstore import get_cache_dir # type: ignore[import-untyped] +from pydantic import IPvAnyAddress + +from ..templates import path +from .avatar import generate_identicon + +app = get_app() + +driver = get_driver() + +global_config = driver.config + +cache_dir = get_cache_dir('nonebot_plugin_tetris_stats') + +if not isinstance(app, FastAPI): + raise RuntimeError('本插件需要 FastAPI 驱动器才能运行') # noqa: TRY004 + +NOT_FOUND = HTMLResponse('404 Not Found', status_code=status.HTTP_404_NOT_FOUND) + + +class HostPage: + pages: ClassVar[dict[str, str]] = {} + + def __init__(self, page: str) -> None: + self.page_hash = sha256(page.encode()).hexdigest() + self.pages[self.page_hash] = page + + async def __aenter__(self) -> str: + return self.page_hash + + async def __aexit__(self, exc_type, exc, tb) -> None: # noqa: ANN001 + self.pages.pop(self.page_hash, None) + + +app.mount( + '/static', + StaticFiles(directory=path), + name='static', +) + + +@app.get('/host/page/{page_hash}.html', status_code=status.HTTP_200_OK) +async def _(page_hash: str) -> HTMLResponse: + if page_hash in HostPage.pages: + return HTMLResponse(HostPage.pages[page_hash]) + return NOT_FOUND + + +@app.get('/identicon') +async def _(md5: str = Query(regex=r'^[a-fA-F0-9]{32}$')): + identicon_path = cache_dir / 'identicon' / f'{md5}.svg' + if identicon_path.exists() is False: + identicon_path.parent.mkdir(parents=True, exist_ok=True) + result = await generate_identicon(md5) + async with open(identicon_path, mode='xb') as file: + await file.write(result) + return Response(result, media_type='image/svg+xml') + logger.debug('Identicon Cache hit!') + return FileResponse(identicon_path, media_type='image/svg+xml') + + +def get_self_netloc() -> str: + host: IPv4Address | IPv6Address | IPvAnyAddress = global_config.host + if isinstance(host, IPv4Address): + if host == IPv4Address('0.0.0.0'): # noqa: S104 + host = IPv4Address('127.0.0.1') + netloc = f'{host}:{global_config.port}' + else: + if host == IPv6Address('::'): + host = IPv6Address('::1') + netloc = f'[{host}]:{global_config.port}' + return netloc diff --git a/nonebot_plugin_tetris_stats/utils/render.py b/nonebot_plugin_tetris_stats/utils/render.py new file mode 100644 index 0000000..1f27164 --- /dev/null +++ b/nonebot_plugin_tetris_stats/utils/render.py @@ -0,0 +1,69 @@ +from typing import Any, Literal, overload + +from jinja2 import Environment, FileSystemLoader + +from ..game_data_processor.io_data_processor.typing import Rank +from ..templates import path +from .typing import GameType + +Bind = Literal['bind.j2.html'] +Data = Literal['data.j2.html'] + +env = Environment( + loader=FileSystemLoader(path), autoescape=True, trim_blocks=True, lstrip_blocks=True, enable_async=True +) + + +@overload +async def render( + template: Bind, + *, + user_avatar: str, + state: Literal['error', 'success', 'unknown', 'unlink', 'unverified'], + bot_avatar: str, + game_type: GameType, + user_name: str, + bot_name: str, + command: str, +) -> str: ... + + +@overload +async def render( + template: Data, + *, + user_avatar: str, + user_name: str, + user_sign: str, + game_type: Literal['TETR.IO'], + ranking: str | float, + rd: str | float, + rank: Rank, + TR: str | float, # noqa: N803 + global_rank: str | int, + lpm: str | float, + pps: str | float, + apm: str | float, + apl: str | float, + adpm: str | float, + adpl: str | float, + vs: str | float, + sprint: str, + blitz: str, + data: list[list[int]], + split_value: int, + value_max: int, + value_min: int, + offset: int, + app: str | float, + dspp: str | float, + OR: str | float, # noqa: N803 + ci: str | float, + ge: str | float, +) -> str: ... + + +async def render(template: Bind | Data, **kwargs: Any) -> str: + if kwargs['game_type'] == 'IO': + kwargs['game_type'] = 'TETR.IO' + return await env.get_template(template).render_async(**kwargs) diff --git a/nonebot_plugin_tetris_stats/utils/screenshot.py b/nonebot_plugin_tetris_stats/utils/screenshot.py new file mode 100644 index 0000000..91ee402 --- /dev/null +++ b/nonebot_plugin_tetris_stats/utils/screenshot.py @@ -0,0 +1,10 @@ +from .browser import BrowserManager + + +async def screenshot(url: str) -> bytes: + browser = await BrowserManager.get_browser() + async with ( + await browser.new_page(no_viewport=True, viewport={'width': 0, 'height': 0}) as page, + ): + await page.goto(url) + return await page.screenshot(full_page=True, type='png') diff --git a/poetry.lock b/poetry.lock index a8dc4f2..16262d9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -127,13 +127,13 @@ zookeeper = ["kazoo"] [[package]] name = "arclet-alconna" -version = "1.8.10" +version = "1.8.11" description = "A High-performance, Generality, Humane Command Line Arguments Parser Library." optional = false python-versions = ">=3.8" files = [ - {file = "arclet_alconna-1.8.10-py3-none-any.whl", hash = "sha256:6c4d464e3c1b3c03bce301f51370648fd006df2b820e6f926cb410ced97f0c2f"}, - {file = "arclet_alconna-1.8.10.tar.gz", hash = "sha256:379e824919a2750f43a2b87a4a523bf06386b4469c5ace859d47213857606c3e"}, + {file = "arclet_alconna-1.8.11-py3-none-any.whl", hash = "sha256:8a0c188400214abe2b72b2e6f4f23ed8d3021270654c15bc46cad62b725b7a44"}, + {file = "arclet_alconna-1.8.11.tar.gz", hash = "sha256:3fed5e946709d63b9d7ee7cddf32b145e1f931b8ea9d0b8174cac753d965e9c8"}, ] [package.dependencies] @@ -159,6 +159,17 @@ files = [ arclet-alconna = ">=1.8.10" nepattern = ">=0.7.0,<1.0.0" +[[package]] +name = "cachetools" +version = "5.3.3" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, + {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, +] + [[package]] name = "certifi" version = "2024.2.2" @@ -270,6 +281,20 @@ files = [ {file = "cssselect-1.2.0.tar.gz", hash = "sha256:666b19839cfaddb9ce9d36bfe4c969132c647b92fc9088c4e23f786b30f1b3dc"}, ] +[[package]] +name = "emoji" +version = "2.11.1" +description = "Emoji for Python" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +files = [ + {file = "emoji-2.11.1-py2.py3-none-any.whl", hash = "sha256:b7ba25299bbf520cc8727848ae66b986da32aee27dc2887eaea2bff07226ce49"}, + {file = "emoji-2.11.1.tar.gz", hash = "sha256:062ff0b3154b6219143f8b9f4b3e5c64c35bc2b146e6e2349ab5f29e218ce1ee"}, +] + +[package.extras] +dev = ["coverage", "coveralls", "pytest"] + [[package]] name = "exceptiongroup" version = "1.2.1" @@ -286,13 +311,13 @@ test = ["pytest (>=6)"] [[package]] name = "fastapi" -version = "0.110.2" +version = "0.110.3" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi-0.110.2-py3-none-any.whl", hash = "sha256:239403f2c0a3dda07a9420f95157a7f014ddb2b770acdbc984f9bdf3ead7afdb"}, - {file = "fastapi-0.110.2.tar.gz", hash = "sha256:b53d673652da3b65e8cd787ad214ec0fe303cad00d2b529b86ce7db13f17518d"}, + {file = "fastapi-0.110.3-py3-none-any.whl", hash = "sha256:fd7600612f755e4050beb74001310b5a7e1796d149c2ee363124abdfa0289d32"}, + {file = "fastapi-0.110.3.tar.gz", hash = "sha256:555700b0159379e94fdbfc6bb66a0f1c43f4cf7060f25239af3d84b63a656626"}, ] [package.dependencies] @@ -301,7 +326,7 @@ starlette = ">=0.37.2,<0.38.0" typing-extensions = ">=4.8.0" [package.extras] -all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "greenlet" @@ -489,6 +514,25 @@ files = [ {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, ] +[[package]] +name = "importlib-metadata" +version = "7.1.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, + {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] + [[package]] name = "importlib-resources" version = "6.4.0" @@ -504,6 +548,23 @@ files = [ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] testing = ["jaraco.test (>=5.4)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] +[[package]] +name = "jinja2" +version = "3.1.3" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + [[package]] name = "loguru" version = "0.7.2" @@ -621,6 +682,7 @@ files = [ {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:9e2addd2d1866fe112bc6f80117bcc6bc25191c5ed1bfbcf9f1386a884252ae8"}, {file = "lxml-5.2.1-cp37-cp37m-win32.whl", hash = "sha256:f51969bac61441fd31f028d7b3b45962f3ecebf691a510495e5d2cd8c8092dbd"}, {file = "lxml-5.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b0b58fbfa1bf7367dde8a557994e3b1637294be6cf2169810375caf8571a085c"}, + {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3e183c6e3298a2ed5af9d7a356ea823bccaab4ec2349dc9ed83999fd289d14d5"}, {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:804f74efe22b6a227306dd890eecc4f8c59ff25ca35f1f14e7482bbce96ef10b"}, {file = "lxml-5.2.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:08802f0c56ed150cc6885ae0788a321b73505d2263ee56dad84d200cab11c07a"}, {file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f8c09ed18ecb4ebf23e02b8e7a22a05d6411911e6fabef3a36e4f371f4f2585"}, @@ -1004,13 +1066,13 @@ files = [ [[package]] name = "nepattern" -version = "0.7.1" +version = "0.7.2" description = "a complex pattern, support typing" optional = false python-versions = ">=3.8" files = [ - {file = "nepattern-0.7.1-py3-none-any.whl", hash = "sha256:e5190a79d398dce72f972ffafc413653414cca12a1dac56d38fcf070d2f034bc"}, - {file = "nepattern-0.7.1.tar.gz", hash = "sha256:14bae0dfa93241f3c2d8371cfc5e51072a186a295a7d35fbd7a60b08e83b2605"}, + {file = "nepattern-0.7.2-py3-none-any.whl", hash = "sha256:75406623a4a533628a6fb1996a7cc79d7b535a268e2a8bf4b405197175baecca"}, + {file = "nepattern-0.7.2.tar.gz", hash = "sha256:7869e7998d870c920611b7a25649fb451c57bf2de450fb5d2e87408ff2917885"}, ] [package.dependencies] @@ -1079,20 +1141,21 @@ nonebot2 = ">=2.2.0" [[package]] name = "nonebot-plugin-alconna" -version = "0.45.0" +version = "0.45.2" description = "Alconna Adapter for Nonebot" optional = false python-versions = ">=3.9" files = [ - {file = "nonebot_plugin_alconna-0.45.0-py3-none-any.whl", hash = "sha256:3394961dc27f2322e8ebb8e5f700b567b3749262689c3a0f85fab55112bc050e"}, - {file = "nonebot_plugin_alconna-0.45.0.tar.gz", hash = "sha256:6fa530ef6df02c3b8c2a67979ac55d6978cc647df2ce5a393c87f42e919be641"}, + {file = "nonebot_plugin_alconna-0.45.2-py3-none-any.whl", hash = "sha256:38461346f52479c3133d9a789cca1d280a05834790dbadeecfc88639a1e326a2"}, + {file = "nonebot_plugin_alconna-0.45.2.tar.gz", hash = "sha256:a54bd294c0a829fcd344a3d3f5b9b040c1dcdbe739245557037cca019187d031"}, ] [package.dependencies] -arclet-alconna = ">=1.8.10" +arclet-alconna = ">=1.8.11" arclet-alconna-tools = ">=0.7.3" -nepattern = ">=0.7.0" -nonebot2 = ">=2.2.1" +importlib-metadata = ">=4.13.0" +nepattern = ">=0.7.2" +nonebot2 = ">=2.3.0" [[package]] name = "nonebot-plugin-apscheduler" @@ -1160,6 +1223,24 @@ postgresql = ["sqlalchemy[postgresql-psycopgbinary]"] psycopg = ["sqlalchemy[postgresql-psycopgbinary]"] sqlite = ["sqlalchemy[aiosqlite]"] +[[package]] +name = "nonebot-plugin-userinfo" +version = "0.2.4" +description = "Nonebot2 用户信息获取插件" +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "nonebot_plugin_userinfo-0.2.4-py3-none-any.whl", hash = "sha256:f08dac58759b859f8bf1d1c17e96cdcee92b10613631a430405364a40181f9e4"}, + {file = "nonebot_plugin_userinfo-0.2.4.tar.gz", hash = "sha256:1d49ff00ce38c856be4388fc2a954656f07cc529ce38ef9593e3a0ea40f26b6a"}, +] + +[package.dependencies] +cachetools = ">=5.0.0,<6.0.0" +emoji = ">=2.0.0,<3.0.0" +httpx = ">=0.20.0,<1.0.0" +nonebot2 = ">=2.0.0,<3.0.0" +strenum = ">=0.4.8,<0.5.0" + [[package]] name = "nonebot2" version = "2.3.0" @@ -1254,7 +1335,6 @@ optional = false python-versions = ">=3.9" files = [ {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, - {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, @@ -1275,7 +1355,6 @@ files = [ {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, - {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, @@ -1334,6 +1413,92 @@ files = [ numpy = {version = ">=1.26.0", markers = "python_version < \"3.13\""} types-pytz = ">=2022.1.1" +[[package]] +name = "pillow" +version = "10.3.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pillow-10.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45"}, + {file = "pillow-10.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf"}, + {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3"}, + {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5"}, + {file = "pillow-10.3.0-cp310-cp310-win32.whl", hash = "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2"}, + {file = "pillow-10.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f"}, + {file = "pillow-10.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b"}, + {file = "pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795"}, + {file = "pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd"}, + {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad"}, + {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c"}, + {file = "pillow-10.3.0-cp311-cp311-win32.whl", hash = "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09"}, + {file = "pillow-10.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d"}, + {file = "pillow-10.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f"}, + {file = "pillow-10.3.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84"}, + {file = "pillow-10.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a"}, + {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef"}, + {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3"}, + {file = "pillow-10.3.0-cp312-cp312-win32.whl", hash = "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d"}, + {file = "pillow-10.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b"}, + {file = "pillow-10.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a"}, + {file = "pillow-10.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b"}, + {file = "pillow-10.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd"}, + {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d"}, + {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3"}, + {file = "pillow-10.3.0-cp38-cp38-win32.whl", hash = "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b"}, + {file = "pillow-10.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999"}, + {file = "pillow-10.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936"}, + {file = "pillow-10.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8"}, + {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9"}, + {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb"}, + {file = "pillow-10.3.0-cp39-cp39-win32.whl", hash = "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572"}, + {file = "pillow-10.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb"}, + {file = "pillow-10.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591"}, + {file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + [[package]] name = "playwright" version = "1.43.0" @@ -1755,6 +1920,22 @@ anyio = ">=3.4.0,<5" [package.extras] full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] +[[package]] +name = "strenum" +version = "0.4.15" +description = "An Enum that inherits from str." +optional = false +python-versions = "*" +files = [ + {file = "StrEnum-0.4.15-py3-none-any.whl", hash = "sha256:a30cda4af7cc6b5bf52c8055bc4bf4b2b6b14a93b574626da33df53cf7740659"}, + {file = "StrEnum-0.4.15.tar.gz", hash = "sha256:878fb5ab705442070e4dd1929bb5e2249511c0bcf2b0eeacf3bcd80875c82eff"}, +] + +[package.extras] +docs = ["myst-parser[linkify]", "sphinx", "sphinx-rtd-theme"] +release = ["twine"] +test = ["pylint", "pytest", "pytest-black", "pytest-cov", "pytest-pylint"] + [[package]] name = "tarina" version = "0.4.4" @@ -2419,6 +2600,21 @@ files = [ idna = ">=2.0" multidict = ">=4.0" +[[package]] +name = "zipp" +version = "3.18.1" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"}, + {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] + [[package]] name = "zstandard" version = "0.22.0" @@ -2483,4 +2679,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "78b446052e80cf2d35175fbd319184c1911abeda7924f3e51bfc8d7520308950" +content-hash = "c568aeaa3fa7dc9049bb95fb3f682754aff0be497fa7e097c51d1becb90a84a5" diff --git a/pyproject.toml b/pyproject.toml index 79751e2..9305532 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ license = 'AGPL-3.0' [tool.poetry.dependencies] python = '^3.10' -nonebot2 = '^2.3.0' +nonebot2 = { extras = ["fastapi"], version = "^2.3.0" } lxml = '^5.1.0' pandas = '>=1.4.3,<3.0.0' playwright = '^1.41.2' @@ -23,6 +23,9 @@ nonebot-plugin-alconna = ">=0.40" nonebot-plugin-apscheduler = "^0.4.0" aiocache = "^0.12.2" zstandard = "^0.22.0" +jinja2 = "^3.1.3" +nonebot-plugin-userinfo = "^0.2.4" +pillow = "^10.3.0" [tool.poetry.group.dev.dependencies] mypy = '>=1.9' @@ -30,7 +33,6 @@ types-ujson = '^5.9.0' pandas-stubs = '>=1.5.2,<3.0.0' ruff = '>=0.3.0' types-aiofiles = "^23.2.0.20240106" -nonebot2 = { extras = ["fastapi"], version = "^2.3.0" } types-lxml = "^2024.2.9" nonebot-plugin-orm = { extras = ["default"], version = ">=0.3,<0.8" } nonebot-adapter-onebot = "^2.4.1"