Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: 迁移至 nb orm 插件 #16

Merged
merged 12 commits into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "ORM Upgrade",
"type": "python",
"request": "launch",
"module": "nb-cli",
"args": ["orm", "upgrade"],
"justMyCode": true
},
{
"name": "Run",
"type": "python",
Expand Down
40 changes: 25 additions & 15 deletions nonebot_plugin_user/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require("nonebot_plugin_alconna")
require("nonebot_plugin_session")
require("nonebot_plugin_userinfo")
require("nonebot_plugin_datastore")
require("nonebot_plugin_orm")

import random
from typing import Dict, Optional, Tuple, cast
Expand All @@ -20,8 +20,12 @@
)
from nonebot_plugin_session import SessionLevel

from . import migrations
from .annotated import UserSession as UserSession
from .utils import get_user, remove_bind, set_bind
from .utils import get_user as get_user
from .utils import get_user_by_id as get_user_by_id
from .utils import remove_bind as remove_bind
from .utils import set_bind as set_bind

__plugin_meta__ = PluginMetadata(
name="用户",
Expand All @@ -35,6 +39,7 @@
supported_adapters=inherit_supported_adapters(
"nonebot_plugin_alconna", "nonebot_plugin_session", "nonebot_plugin_userinfo"
),
extra={"orm_version_location": migrations},
)

user_cmd = on_alconna(Alconna("user"), use_cmd_start=True)
Expand All @@ -45,10 +50,10 @@ async def _(session: UserSession):
await user_cmd.finish(
"\n".join(
[
f"用户 ID:{session.uid}",
f"用户 ID:{session.user_id}",
f"用户名:{session.name}",
f"用户创建日期:{session.created_at.strftime('%Y-%m-%d %H:%M:%S')}",
f"用户所在平台 ID:{session.pid}",
f"用户所在平台 ID:{session.platform_id}",
f"用户所在平台:{session.platform}",
]
)
Expand All @@ -73,7 +78,7 @@ async def _(
remove: Query[bool] = AlconnaQuery("r.value", default=False),
):
if remove.result:
result = await remove_bind(session.pid, session.platform)
result = await remove_bind(session.platform_id, session.platform)
if result:
await bind_cmd.finish("解绑成功")
else:
Expand All @@ -82,38 +87,43 @@ async def _(
# 生成令牌
if not token:
token = f"nonebot/{random.randint(100000, 999999)}"
tokens[token] = (session.pid, session.platform, session.uid, session.level)
tokens[token] = (
session.platform_id,
session.platform,
session.user_id,
session.level,
)
await bind_cmd.finish(
f"命令 bind 可用于在多个平台间绑定用户数据。绑定过程中,原始平台的用户数据将完全保留,而目标平台的用户数据将被原始平台的数据所覆盖。\n请确认当前平台是你的目标平台,并在 5 分钟内使用你的账号在原始平台内向机器人发送以下文本:\n/bind {token}\n绑定完成后,你可以随时使用「bind -r」来解除绑定状态。"
)

# 绑定流程
if token in tokens:
# 平台的相关信息
pid, platform, user_id, level = tokens.pop(token)
platform_id, platform, user_id, level = tokens.pop(token)
# 群内绑定的第一步,会在原始平台发送令牌
# 此时 pid 和 platform 为目标平台的信息
# 此时 platform_id 和 platform 为目标平台的信息
if level == SessionLevel.LEVEL2 or level == SessionLevel.LEVEL3:
token = f"nonebot/{random.randint(100000, 999999)}"
tokens[token] = (session.pid, session.platform, user_id, None)
tokens[token] = (session.platform_id, session.platform, user_id, None)
await bind_cmd.finish(
f"令牌核验成功!下面将进行第二步操作。\n请在 5 分钟内使用你的账号在目标平台内向机器人发送以下文本:\n/bind {token}\n注意:当前平台是你的原始平台,这里的用户数据将覆盖目标平台的数据。"
)
# 群内绑定的第二步,会在目标平台发送令牌
# 此时 pid 和 platform 为原始平台的信息
# 此时 platform_id 和 platform 为原始平台的信息
# 需要重新获取其用户信息,然后将目标平台绑定至原始平台
elif level is None:
if session.uid != user_id:
if session.user_id != user_id:
await bind_cmd.finish("请使用最开始要绑定账号进行操作")

user = await get_user(pid, platform)
await set_bind(session.pid, session.platform, user.id)
user = await get_user(platform_id, platform)
await set_bind(session.platform_id, session.platform, user.id)
await bind_cmd.finish("绑定成功")
# 私聊绑定时,会在原始平台发送令牌
# 此时 pid 和 platform 为目标平台的信息
# 此时 platform_id 和 platform 为目标平台的信息
# 直接将目标平台绑定至原始平台
elif level == SessionLevel.LEVEL1:
await set_bind(pid, platform, session.uid)
await set_bind(platform_id, platform, session.user_id)
await bind_cmd.finish("绑定成功")
else:
await bind_cmd.finish("令牌不存在或已过期")

This file was deleted.

50 changes: 0 additions & 50 deletions nonebot_plugin_user/migrations/8aa030575da8_init_db.py

This file was deleted.

63 changes: 63 additions & 0 deletions nonebot_plugin_user/migrations/ac57f7074e58_init_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""init db

修订 ID: ac57f7074e58
父修订:
创建时间: 2023-10-07 10:09:49.921974

"""
from __future__ import annotations

from collections.abc import Sequence

import sqlalchemy as sa
from alembic import op

revision: str = "ac57f7074e58"
down_revision: str | Sequence[str] | None = None
branch_labels: str | Sequence[str] | None = ("nonebot_plugin_user",)
depends_on: str | Sequence[str] | None = None


def upgrade(name: str = "") -> None:
if name:
return
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"nonebot_plugin_user_user",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.String(length=255), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=False),
sa.PrimaryKeyConstraint("id", name=op.f("pk_nonebot_plugin_user_user")),
)
op.create_table(
"nonebot_plugin_user_bind",
sa.Column("platform", sa.String(length=32), nullable=False),
sa.Column("platform_id", sa.String(length=64), nullable=False),
sa.Column("bind_id", sa.Integer(), nullable=False),
sa.Column("original_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["bind_id"],
["nonebot_plugin_user_user.id"],
name=op.f("fk_nonebot_plugin_user_bind_bind_id_nonebot_plugin_user_user"),
),
sa.ForeignKeyConstraint(
["original_id"],
["nonebot_plugin_user_user.id"],
name=op.f(
"fk_nonebot_plugin_user_bind_original_id_nonebot_plugin_user_user"
),
),
sa.PrimaryKeyConstraint(
"platform", "platform_id", name=op.f("pk_nonebot_plugin_user_bind")
),
)
# ### end Alembic commands ###


def downgrade(name: str = "") -> None:
if name:
return
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("nonebot_plugin_user_bind")
op.drop_table("nonebot_plugin_user_user")
# ### end Alembic commands ###
33 changes: 18 additions & 15 deletions nonebot_plugin_user/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,45 @@
from datetime import datetime
from typing import List, Optional

from nonebot_plugin_datastore import get_plugin_data
from nonebot_plugin_orm import Model
from nonebot_plugin_session import Session, SessionIdType, SessionLevel
from nonebot_plugin_userinfo import UserInfo
from sqlalchemy import DateTime, ForeignKey, String
from sqlalchemy.orm import Mapped, mapped_column, relationship

Model = get_plugin_data().Model


class User(Model):
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(255))
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

binds: Mapped[List["Bind"]] = relationship(
back_populates="auser", foreign_keys="[Bind.aid]"
back_populates="bind_user", foreign_keys="[Bind.bind_id]"
)
"""当前绑定的平台"""
bind: Mapped["Bind"] = relationship(
back_populates="buser", foreign_keys="[Bind.bid]"
back_populates="original_user", foreign_keys="[Bind.original_id]"
)
"""初始时绑定的平台"""


class Bind(Model):
pid: Mapped[str] = mapped_column(String(64), primary_key=True)
"""平台 ID"""
platform: Mapped[str] = mapped_column(String(32), primary_key=True)
"""平台名称"""
aid: Mapped[int] = mapped_column(ForeignKey("nonebot_plugin_user_user.id"))
platform_id: Mapped[str] = mapped_column(String(64), primary_key=True)
"""平台 ID"""
bind_id: Mapped[int] = mapped_column(ForeignKey("nonebot_plugin_user_user.id"))
"""当前绑定的账号 ID"""
bid: Mapped[int] = mapped_column(ForeignKey("nonebot_plugin_user_user.id"))
original_id: Mapped[int] = mapped_column(ForeignKey("nonebot_plugin_user_user.id"))
"""初始时绑定的账号 ID"""
auser: Mapped[User] = relationship(back_populates="binds", foreign_keys=[aid])

bind_user: Mapped[User] = relationship(
back_populates="binds", foreign_keys=[bind_id]
)
"""当前绑定的账号"""
buser: Mapped[User] = relationship(back_populates="bind", foreign_keys=[bid])
original_user: Mapped[User] = relationship(
back_populates="bind", foreign_keys=[original_id]
)
"""初始时绑定的账号"""


Expand All @@ -48,7 +51,7 @@ class UserSession:
user: User

@property
def uid(self) -> int:
def user_id(self) -> int:
"""用户 ID"""
return self.user.id

Expand All @@ -63,7 +66,7 @@ def created_at(self) -> datetime:
return self.user.created_at.astimezone()

@property
def pid(self) -> str:
def platform_id(self) -> str:
"""用户所在平台 ID"""
assert self.session.id1
return self.session.id1
Expand All @@ -79,8 +82,8 @@ def level(self) -> SessionLevel:
return self.session.level

@property
def group_id(self) -> str:
"""用户所在群组 ID
def group_session_id(self) -> str:
"""用户所在群组会话 ID

ID 由平台名称和平台的群组 ID 组成,例如 `qq_123456789`。
"""
Expand Down
Loading
Loading