mirror of
https://github.com/A-Minos/nonebot-plugin-tetris-stats.git
synced 2026-03-05 05:36:54 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 03d34c5572 | |||
| 04b480ef52 | |||
| 5563b01937 |
@@ -0,0 +1,103 @@
|
|||||||
|
"""Add user_unique_identifier field to HistoricalData
|
||||||
|
|
||||||
|
迁移 ID: b7fbdafc339a
|
||||||
|
父迁移: 8a91210ce14d
|
||||||
|
创建时间: 2024-05-07 16:55:29.527215
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Sequence
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from alembic import op
|
||||||
|
from nonebot.log import logger
|
||||||
|
|
||||||
|
revision: str = 'b7fbdafc339a'
|
||||||
|
down_revision: str | Sequence[str] | None = '8a91210ce14d'
|
||||||
|
branch_labels: str | Sequence[str] | None = None
|
||||||
|
depends_on: str | Sequence[str] | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(name: str = '') -> None:
|
||||||
|
if name:
|
||||||
|
return
|
||||||
|
from nonebot_plugin_tetris_stats.version import __version__
|
||||||
|
|
||||||
|
if __version__ != '1.0.4':
|
||||||
|
logger.critical('本迁移需要1.0.4版本, 请先锁定版本至1.0.4版本再执行本迁移')
|
||||||
|
raise RuntimeError('本迁移需要1.0.4版本, 请先锁定版本至1.0.4版本再执行本迁移')
|
||||||
|
from nonebot.compat import type_validate_json
|
||||||
|
from pydantic import ValidationError
|
||||||
|
from rich.progress import (
|
||||||
|
BarColumn,
|
||||||
|
MofNCompleteColumn,
|
||||||
|
Progress,
|
||||||
|
TaskProgressColumn,
|
||||||
|
TextColumn,
|
||||||
|
TimeRemainingColumn,
|
||||||
|
)
|
||||||
|
from sqlalchemy import select
|
||||||
|
from sqlalchemy.ext.automap import automap_base
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from nonebot_plugin_tetris_stats.game_data_processor.schemas import BaseUser
|
||||||
|
|
||||||
|
with op.batch_alter_table('nonebot_plugin_tetris_stats_historicaldata', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('user_unique_identifier', sa.String(length=32), nullable=True))
|
||||||
|
batch_op.create_index(
|
||||||
|
batch_op.f('ix_nonebot_plugin_tetris_stats_historicaldata_user_unique_identifier'),
|
||||||
|
['user_unique_identifier'],
|
||||||
|
unique=False,
|
||||||
|
)
|
||||||
|
Base = automap_base() # noqa: N806
|
||||||
|
connection = op.get_bind()
|
||||||
|
Base.prepare(autoload_with=connection)
|
||||||
|
HistoricalData = Base.classes.nonebot_plugin_tetris_stats_historicaldata # noqa: N806
|
||||||
|
|
||||||
|
models: list[type[BaseUser]] = BaseUser.__subclasses__()
|
||||||
|
|
||||||
|
def json_to_model(value: str) -> BaseUser:
|
||||||
|
for i in models:
|
||||||
|
try:
|
||||||
|
return type_validate_json(i, value)
|
||||||
|
except ValidationError: # noqa: PERF203
|
||||||
|
...
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
with Session(op.get_bind()) as session:
|
||||||
|
count = session.query(HistoricalData).count()
|
||||||
|
with Progress(
|
||||||
|
TextColumn('[progress.description]{task.description}'),
|
||||||
|
BarColumn(),
|
||||||
|
MofNCompleteColumn(),
|
||||||
|
TaskProgressColumn(),
|
||||||
|
TimeRemainingColumn(),
|
||||||
|
) as progress:
|
||||||
|
task_id = progress.add_task('[cyan]Updateing:', total=count)
|
||||||
|
for i in range(0, count, 100):
|
||||||
|
for j in session.scalars(
|
||||||
|
select(HistoricalData).where(HistoricalData.id > i).order_by(HistoricalData.id).limit(100)
|
||||||
|
):
|
||||||
|
model = json_to_model(j.game_user)
|
||||||
|
try:
|
||||||
|
j.user_unique_identifier = model.unique_identifier
|
||||||
|
except ValueError:
|
||||||
|
session.delete(j)
|
||||||
|
progress.update(task_id, advance=1)
|
||||||
|
session.commit()
|
||||||
|
with op.batch_alter_table('nonebot_plugin_tetris_stats_historicaldata', schema=None) as batch_op:
|
||||||
|
batch_op.alter_column('user_unique_identifier', existing_type=sa.VARCHAR(length=32), nullable=False)
|
||||||
|
logger.success('database upgrade success')
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade(name: str = '') -> None:
|
||||||
|
if name:
|
||||||
|
return
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('nonebot_plugin_tetris_stats_historicaldata', schema=None) as batch_op:
|
||||||
|
batch_op.drop_index(batch_op.f('ix_nonebot_plugin_tetris_stats_historicaldata_user_unique_identifier'))
|
||||||
|
batch_op.drop_column('user_unique_identifier')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -70,6 +70,7 @@ class HistoricalData(MappedAsDataclass, Model):
|
|||||||
game_platform: Mapped[GameType] = mapped_column(String(32), index=True, init=False)
|
game_platform: Mapped[GameType] = mapped_column(String(32), index=True, init=False)
|
||||||
command_type: Mapped[CommandType] = mapped_column(String(16), index=True, init=False)
|
command_type: Mapped[CommandType] = mapped_column(String(16), index=True, init=False)
|
||||||
command_args: Mapped[list[str]] = mapped_column(JSON, init=False)
|
command_args: Mapped[list[str]] = mapped_column(JSON, init=False)
|
||||||
|
user_unique_identifier: Mapped[str] = mapped_column(String(32), index=True, init=False)
|
||||||
game_user: Mapped[BaseUser] = mapped_column(PydanticType(get_model=BaseUser.__subclasses__), init=False)
|
game_user: Mapped[BaseUser] = mapped_column(PydanticType(get_model=BaseUser.__subclasses__), init=False)
|
||||||
processed_data: Mapped[BaseProcessedData] = mapped_column(
|
processed_data: Mapped[BaseProcessedData] = mapped_column(
|
||||||
PydanticType(get_model=BaseProcessedData.__subclasses__), init=False
|
PydanticType(get_model=BaseProcessedData.__subclasses__), init=False
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ class Processor(ABC):
|
|||||||
historical_data.game_platform = self.game_platform
|
historical_data.game_platform = self.game_platform
|
||||||
historical_data.command_type = self.command_type
|
historical_data.command_type = self.command_type
|
||||||
historical_data.command_args = self.command_args
|
historical_data.command_args = self.command_args
|
||||||
|
historical_data.user_unique_identifier = self.user.unique_identifier
|
||||||
historical_data.game_user = self.user
|
historical_data.game_user = self.user
|
||||||
historical_data.processed_data = self.processed_data
|
historical_data.processed_data = self.processed_data
|
||||||
historical_data.finish_time = finish_time
|
historical_data.finish_time = finish_time
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
from nonebot.compat import PYDANTIC_V2
|
from pydantic import BaseModel, Field
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
|
||||||
|
|
||||||
from ..typing import Rank
|
from ..typing import Rank
|
||||||
from .base import FailedModel
|
from .base import FailedModel
|
||||||
@@ -14,12 +13,6 @@ class _User(BaseModel):
|
|||||||
supporter: bool
|
supporter: bool
|
||||||
verified: bool
|
verified: bool
|
||||||
country: str | None = None
|
country: str | None = None
|
||||||
if PYDANTIC_V2:
|
|
||||||
model_config = ConfigDict(populate_by_name=True)
|
|
||||||
else:
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
allow_population_by_field_name = True
|
|
||||||
|
|
||||||
|
|
||||||
class SuccessModel(BaseSuccessModel):
|
class SuccessModel(BaseSuccessModel):
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
from nonebot.compat import PYDANTIC_V2
|
from pydantic import BaseModel, Field
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
|
||||||
|
|
||||||
from ..typing import Rank
|
from ..typing import Rank
|
||||||
from .base import FailedModel
|
from .base import FailedModel
|
||||||
@@ -114,12 +113,6 @@ class SuccessModel(BaseSuccessModel):
|
|||||||
connections: Connections
|
connections: Connections
|
||||||
friend_count: int | None = None
|
friend_count: int | None = None
|
||||||
distinguishment: Distinguishment | None = None
|
distinguishment: Distinguishment | None = None
|
||||||
if PYDANTIC_V2:
|
|
||||||
model_config = ConfigDict(populate_by_name=True)
|
|
||||||
else:
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
allow_population_by_field_name = True
|
|
||||||
|
|
||||||
user: User
|
user: User
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from nonebot.compat import PYDANTIC_V2
|
from pydantic import BaseModel, Field
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
|
||||||
|
|
||||||
from .base import FailedModel
|
from .base import FailedModel
|
||||||
from .base import SuccessModel as BaseSuccessModel
|
from .base import SuccessModel as BaseSuccessModel
|
||||||
@@ -67,23 +66,11 @@ class EndContext(BaseModel):
|
|||||||
finesse: Finesse
|
finesse: Finesse
|
||||||
final_time: float = Field(..., alias='finalTime')
|
final_time: float = Field(..., alias='finalTime')
|
||||||
gametype: str
|
gametype: str
|
||||||
if PYDANTIC_V2:
|
|
||||||
model_config = ConfigDict(populate_by_name=True)
|
|
||||||
else:
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
allow_population_by_field_name = True
|
|
||||||
|
|
||||||
|
|
||||||
class _User(BaseModel):
|
class _User(BaseModel):
|
||||||
id: str = Field(..., alias='_id')
|
id: str = Field(..., alias='_id')
|
||||||
username: str
|
username: str
|
||||||
if PYDANTIC_V2:
|
|
||||||
model_config = ConfigDict(populate_by_name=True)
|
|
||||||
else:
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
allow_population_by_field_name = True
|
|
||||||
|
|
||||||
|
|
||||||
class _Record(BaseModel):
|
class _Record(BaseModel):
|
||||||
@@ -93,12 +80,6 @@ class _Record(BaseModel):
|
|||||||
user: _User
|
user: _User
|
||||||
ts: datetime
|
ts: datetime
|
||||||
ismulti: bool | None = None
|
ismulti: bool | None = None
|
||||||
if PYDANTIC_V2:
|
|
||||||
model_config = ConfigDict(populate_by_name=True)
|
|
||||||
else:
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
allow_population_by_field_name = True
|
|
||||||
|
|
||||||
|
|
||||||
class BaseModeRecord(BaseModel):
|
class BaseModeRecord(BaseModel):
|
||||||
@@ -121,12 +102,6 @@ class SuccessModel(BaseSuccessModel):
|
|||||||
|
|
||||||
sprint: Sprint = Field(..., alias='40l')
|
sprint: Sprint = Field(..., alias='40l')
|
||||||
blitz: Blitz
|
blitz: Blitz
|
||||||
if PYDANTIC_V2:
|
|
||||||
model_config = ConfigDict(populate_by_name=True)
|
|
||||||
else:
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
allow_population_by_field_name = True
|
|
||||||
|
|
||||||
class Zen(BaseModel):
|
class Zen(BaseModel):
|
||||||
level: int
|
level: int
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
from nonebot.compat import PYDANTIC_V2
|
from pydantic import BaseModel, Field
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
|
||||||
|
|
||||||
|
|
||||||
class SuccessModel(BaseModel):
|
class SuccessModel(BaseModel):
|
||||||
@@ -17,12 +16,6 @@ class SuccessModel(BaseModel):
|
|||||||
win: str
|
win: str
|
||||||
lose: str
|
lose: str
|
||||||
score: str
|
score: str
|
||||||
if PYDANTIC_V2:
|
|
||||||
model_config = ConfigDict(populate_by_name=True)
|
|
||||||
else:
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
allow_population_by_field_name = True
|
|
||||||
|
|
||||||
class UserDataTotalItem(BaseModel):
|
class UserDataTotalItem(BaseModel):
|
||||||
time_map: str = Field(..., alias='timeMap')
|
time_map: str = Field(..., alias='timeMap')
|
||||||
@@ -55,12 +48,6 @@ class SuccessModel(BaseModel):
|
|||||||
tspin_no_map: str = Field(..., alias='tspinNoMap')
|
tspin_no_map: str = Field(..., alias='tspinNoMap')
|
||||||
b2b_no_map: str = Field(..., alias='b2bNoMap')
|
b2b_no_map: str = Field(..., alias='b2bNoMap')
|
||||||
perfect_clear_no_map: str = Field(..., alias='perfectClearNoMap')
|
perfect_clear_no_map: str = Field(..., alias='perfectClearNoMap')
|
||||||
if PYDANTIC_V2:
|
|
||||||
model_config = ConfigDict(populate_by_name=True)
|
|
||||||
else:
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
allow_population_by_field_name = True
|
|
||||||
|
|
||||||
teaid: str = Field(..., alias='teaId')
|
teaid: str = Field(..., alias='teaId')
|
||||||
name: str
|
name: str
|
||||||
@@ -85,13 +72,6 @@ class SuccessModel(BaseModel):
|
|||||||
register_date: datetime = Field(..., alias='registerDate')
|
register_date: datetime = Field(..., alias='registerDate')
|
||||||
last_login_date: datetime = Field(..., alias='lastLoginDate')
|
last_login_date: datetime = Field(..., alias='lastLoginDate')
|
||||||
|
|
||||||
if PYDANTIC_V2:
|
|
||||||
model_config = ConfigDict(populate_by_name=True)
|
|
||||||
else:
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
allow_population_by_field_name = True
|
|
||||||
|
|
||||||
code: int
|
code: int
|
||||||
success: Literal[True]
|
success: Literal[True]
|
||||||
data: Data
|
data: Data
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = 'nonebot-plugin-tetris-stats'
|
name = 'nonebot-plugin-tetris-stats'
|
||||||
version = '1.0.3'
|
version = '1.0.4'
|
||||||
description = '一款基于 NoneBot2 的用于查询 Tetris 相关游戏数据的插件'
|
description = '一款基于 NoneBot2 的用于查询 Tetris 相关游戏数据的插件'
|
||||||
authors = ['scdhh <wallfjjd@gmail.com>']
|
authors = ['scdhh <wallfjjd@gmail.com>']
|
||||||
readme = 'README.md'
|
readme = 'README.md'
|
||||||
|
|||||||
Reference in New Issue
Block a user