refactor: ユーザーモデルを作り直した #108

pull/110/head
yupix 10 months ago
parent ecc8b9b9c5
commit dc3978bc98
No known key found for this signature in database
GPG Key ID: 2FF705F5C56D9C06

@ -1,10 +1,10 @@
from __future__ import annotations
from datetime import datetime
from typing import TYPE_CHECKING, Generic, Literal, TypeVar, overload
from typing import TYPE_CHECKING, TypeVar, Generic
from mipac.types.meta import IPolicies
from mipac.abstract.model import AbstractModel
from mipac.config import config
from mipac.models.announcement import Announcement
from mipac.models.lite.role import PartialRole
from mipac.models.lite.user import BadgeRole, PartialUser
@ -14,22 +14,20 @@ from mipac.types.user import (
IAchievement,
IBlockingUser,
IFfVisibility,
IMeDetailed,
IMeDetailedModerator,
IUser,
IUserDetailed,
IUserDetailedModerator,
IUserDetailedNotLogined,
IUserField,
IUserNotify,
IUserRole,
is_me_detailed,
is_me_detailed_moderator,
is_partial_user,
is_user_detailed,
is_user_detailed_moderator,
is_user_detailed_not_logined,
IUserDetailedNotMeSchema,
IMeDetailedOnlySchema,
ITwoFactorBackupCodesStock,
NotificationRecieveConfig,
EmailNotificationTypes,
IUserSecurityKey,
IMeDetailedSchema,
IUserDetailedNotMeOnlySchema,
is_user_detailed_not_me,
)
from mipac.utils.format import str_to_datetime
from mipac.utils.util import DeprecatedClass
@ -37,11 +35,9 @@ from mipac.utils.util import DeprecatedClass
if TYPE_CHECKING:
from mipac.manager.client import ClientManager
__all__ = ("UserDetailed", "PartialUser", "Achievement", "BlockingUser", "MeDetailed")
__all__ = ("PartialUser", "Achievement", "BlockingUser", "MeDetailed")
T = TypeVar("T", bound=IUserDetailedNotLogined)
U = TypeVar("U", bound=IUserDetailed)
M = TypeVar("M", bound=IMeDetailed)
T = TypeVar("T", bound=IUserDetailedNotMeSchema)
class BlockingUser(AbstractModel):
@ -62,8 +58,8 @@ class BlockingUser(AbstractModel):
return self.__blocking_user_data["blockee_id"]
@property
def blockee(self) -> UserDetailed:
return UserDetailed(self.__blocking_user_data["blockee"], client=self.__client)
def blockee(self) -> UserDetailedNotMe | MeDetailed:
return packed_user(self.__blocking_user_data["blockee"], client=self.__client)
def __eq__(self, __value: object) -> bool:
return isinstance(__value, BlockingUser) and self.id == __value.id
@ -87,16 +83,16 @@ class Achievement(AbstractModel):
class UserField:
def __init__(self, raw_user_field: IUserField, *, client: ClientManager) -> None:
self.__raw_user_field: IUserField = raw_user_field
self._raw_user_field: IUserField = raw_user_field
self.__client: ClientManager = client
@property
def name(self) -> str:
return self.__raw_user_field["name"]
return self._raw_user_field["name"]
@property
def value(self) -> str:
return self.__raw_user_field["value"]
return self._raw_user_field["value"]
@DeprecatedClass(remove_in_version="0.7.0")
@ -125,9 +121,10 @@ class UserRole(BadgeRole[IUserRole]):
return self._data["is_administrator"]
class UserDetailedNotMeOnly(PartialUser[IUserDetailedNotMeSchema]):
def __init__(self, raw_user: IUserDetailedNotMeSchema, *, client: ClientManager) -> None:
super().__init__(raw_user, client=client)
class UserDetailedNotMeOnly:
def __init__(self, raw_user: IUserDetailedNotMeOnlySchema, *, client: ClientManager) -> None:
self._raw_user: IUserDetailedNotMeOnlySchema = raw_user
self._client: ClientManager = client
@property
def url(self) -> str | None:
@ -274,236 +271,47 @@ class UserDetailedNotMeOnly(PartialUser[IUserDetailedNotMeSchema]):
@property
def is_followed(self) -> bool | None:
return self._raw_user.get("is_followed")
@property
def has_pending_follow_request_from_you(self) -> bool | None:
return self._raw_user.get("has_pending_follow_request_from_you")
@property
def has_pending_follow_request_to_you(self) -> bool | None:
return self._raw_user.get("has_pending_follow_request_to_you")
@property
def is_blocking(self) -> bool | None:
return self._raw_user.get("is_blocking")
@property
def is_blocked(self) -> bool | None:
return self._raw_user.get("is_blocked")
@property
def is_muted(self) -> bool | None:
return self._raw_user.get("is_muted")
@property
def is_renote_muted(self) -> bool | None:
return self._raw_user.get("is_renote_muted")
@property
def notify(self) -> IUserNotify | None:
return self._raw_user.get("notify")
@property
def with_replies(self) -> bool | None:
return self._raw_user.get("with_replies")
class UserDetailedNotLogined(PartialUser[T], Generic[T]):
def __init__(self, raw_user: T, *, client: ClientManager) -> None:
super().__init__(raw_user, client=client)
@property
def url(self) -> str | None:
return self._raw_user["url"]
@property
def uri(self) -> str | None:
return self._raw_user["uri"]
@property
def moved_to(self) -> str | None:
return self._raw_user["moved_to"]
@property
def also_known_as(self) -> list[str] | None:
return self._raw_user["also_known_as"]
@property
def created_at(self) -> datetime:
return str_to_datetime(self._raw_user["created_at"])
@property
def updated_at(self) -> datetime | None:
return (
str_to_datetime(self._raw_user["updated_at"]) if self._raw_user["updated_at"] else None
)
@property
def last_fetched_at(self) -> datetime | None:
return (
str_to_datetime(self._raw_user["last_fetched_at"])
if self._raw_user["last_fetched_at"]
else None
)
@property
def banner_url(self) -> str | None:
return self._raw_user["banner_url"]
@property
def banner_blurhash(self) -> str | None:
return self._raw_user["banner_blurhash"]
@property
def is_locked(self) -> bool:
return self._raw_user["is_locked"]
@property
def is_silenced(self) -> bool:
return self._raw_user["is_silenced"]
@property
def is_suspended(self) -> bool:
return self._raw_user["is_suspended"]
@property
def description(self) -> str | None:
return self._raw_user["description"]
@property
def location(self) -> str | None:
return self._raw_user["location"]
@property
def birthday(self) -> str | None:
return self._raw_user["birthday"]
@property
def lang(self) -> str | None:
return self._raw_user["lang"]
@property
def fields(self) -> list[IUserField]: # TODO: モデル化
return self._raw_user["fields"]
@property
def verified_links(self) -> list[str]:
return self._raw_user["verified_links"]
@property
def followers_count(self) -> int:
return self._raw_user["followers_count"]
@property
def following_count(self) -> int:
return self._raw_user["following_count"]
@property
def notes_count(self) -> int:
return self._raw_user["notes_count"]
@property
def pinned_note_ids(self) -> list[str]:
return self._raw_user["pinned_note_ids"]
@property
def pinned_notes(self) -> list[Note]:
return [Note(raw_note, client=self._client) for raw_note in self._raw_user["pinned_notes"]]
@property
def pinned_page_id(self) -> str | None:
return self._raw_user["pinned_page_id"]
@property
def pinned_page(self) -> IPage | None: # TODO: モデルに
return self._raw_user["pinned_page"]
@property
def public_reactions(self) -> bool:
return self._raw_user["public_reactions"]
@property
def ff_visibility(self) -> IFfVisibility:
return self._raw_user["ff_visibility"]
@property
def two_factor_enabled(self) -> bool:
return self._raw_user["two_factor_enabled"]
@property
def use_password_less_login(self) -> bool:
return self._raw_user["use_password_less_login"]
@property
def security_keys(self) -> bool:
return self._raw_user["security_keys"]
@property
def roles(self) -> list[PartialRole]:
return [PartialRole(raw_role, client=self._client) for raw_role in self._raw_user["roles"]]
@property
def memo(self) -> str | None:
return self._raw_user["memo"]
# TODO: 比較演算子が必要かちょっと後で確認する
class UserDetailed(UserDetailedNotLogined[U], Generic[U]):
def __init__(self, raw_user: U, *, client: ClientManager) -> None:
super().__init__(raw_user, client=client)
@property
def is_following(self) -> bool:
return self._raw_user["is_following"]
@property
def is_followed(self) -> bool:
return self._raw_user["is_followed"]
@property
def has_pending_follow_request_from_you(self) -> bool:
return self._raw_user["has_pending_follow_request_from_you"]
@property
def has_pending_follow_request_to_you(self) -> bool:
return self._raw_user["has_pending_follow_request_to_you"]
@property
def is_blocking(self) -> bool:
return self._raw_user["is_blocking"]
@property
def is_blocked(self) -> bool:
return self._raw_user["is_blocked"]
@property
def is_muted(self) -> bool:
return self._raw_user["is_muted"]
@property
def is_renote_muted(self) -> bool:
return self._raw_user["is_renote_muted"]
@property
def notify(self) -> IUserNotify:
return self._raw_user["notify"]
class UserDetailedModerator(UserDetailed[IUserDetailedModerator]):
def __init__(self, raw_user: IUserDetailedModerator, *, client: ClientManager) -> None:
super().__init__(raw_user, client=client)
@property
def moderation_note(self) -> str:
return self._raw_user["moderation_note"]
class MeDetailed(UserDetailed[M], Generic[M]):
def __init__(self, raw_user: M, *, client: ClientManager) -> None:
super().__init__(raw_user, client=client)
class MeDetailedOnly:
def __init__(self, raw_user: IMeDetailedOnlySchema, *, client: ClientManager) -> None:
self._raw_user: IMeDetailedOnlySchema = raw_user
self.__client: ClientManager = client
@property
def avatar_id(self) -> str:
def avatar_id(self) -> str | None:
return self._raw_user["avatar_id"]
@property
@ -511,11 +319,11 @@ class MeDetailed(UserDetailed[M], Generic[M]):
return self._raw_user["banner_id"]
@property
def is_moderator(self) -> bool:
def is_moderator(self) -> bool | None:
return self._raw_user["is_moderator"]
@property
def is_admin(self) -> bool:
def is_admin(self) -> bool | None:
return self._raw_user["is_admin"]
@property
@ -559,7 +367,7 @@ class MeDetailed(UserDetailed[M], Generic[M]):
return self._raw_user["is_deleted"]
@property
def two_factor_backup_codes_stock(self) -> str:
def two_factor_backup_codes_stock(self) -> ITwoFactorBackupCodesStock:
return self._raw_user["two_factor_backup_codes_stock"]
@property
@ -579,8 +387,10 @@ class MeDetailed(UserDetailed[M], Generic[M]):
return self._raw_user["has_unread_announcement"]
@property
def unread_announcements(self) -> Announcement:
return Announcement(self._raw_user["unread_announcements"], client=self._client)
def unread_announcements(self) -> list[Announcement]:
return [
Announcement(i, client=self.__client) for i in self._raw_user["unread_announcements"]
]
@property
def has_unread_antenna(self) -> bool:
@ -599,93 +409,67 @@ class MeDetailed(UserDetailed[M], Generic[M]):
return self._raw_user["has_pending_received_follow_request"]
@property
def muted_words(self) -> list[str]:
def unread_notifications_count(self) -> int:
return self._raw_user["unread_notifications_count"]
@property
def muted_words(self) -> list[list[str]]:
return self._raw_user["muted_words"]
@property
def muted_instances(self) -> dict:
return self._raw_user["muted_instances"]
def hard_muted_words(self) -> list[list[str]]:
return self._raw_user["hard_muted_words"]
@property
def muting_notification_types(self) -> dict:
return self._raw_user["muting_notification_types"]
def muted_instances(self) -> list[str]:
return self._raw_user["muted_instances"]
@property
def notification_recieve_config(self) -> dict:
def notification_recieve_config(self) -> NotificationRecieveConfig: # TODO: モデル化
return self._raw_user["notification_recieve_config"]
@property
def email_notification_types(self) -> dict:
def email_notification_types(self) -> list[EmailNotificationTypes]: # TODO: モデル化
return self._raw_user["email_notification_types"]
@property
def achievements(self) -> dict:
return self._raw_user["achievements"]
def achievements(self) -> list[Achievement]:
return [Achievement(i) for i in self._raw_user["achievements"]]
@property
def logged_in_days(self) -> int:
return self._raw_user["logged_in_days"]
@property
def policies(self) -> dict:
def policies(self) -> IPolicies: # TODO: モデル化
return self._raw_user["policies"]
@property
def email(self) -> str | None:
return self._raw_user.get("email")
class MeDetailedModerator(MeDetailed):
def __init__(self, raw_user: IMeDetailedModerator, *, client: ClientManager) -> None:
super().__init__(raw_user, client=client)
@property
def email_verified(self) -> bool | None:
return self._raw_user.get("email_verified")
@property
def moderation_note(self) -> str:
return self._raw_user["moderation_note"]
def security_keys_list(self) -> list[IUserSecurityKey] | None: # TODO: モデル化
return self._raw_user.get("security_keys_list")
@overload
def create_user_model(
user: IUser, client: ClientManager, *, use_partial_user: Literal[False]
) -> UserDetailedModels:
pass
class UserDetailedNotMe(PartialUser[T], UserDetailedNotMeOnly, Generic[T]):
def __init__(self, raw_user: T, *, client: ClientManager) -> None:
super().__init__(raw_user, client=client)
@overload
def create_user_model(
user: IUser, client: ClientManager, *, use_partial_user: Literal[True]
) -> UserModels:
pass
class MeDetailed(UserDetailedNotMe[IMeDetailedSchema], MeDetailedOnly):
def __init__(self, raw_user: IMeDetailedSchema, *, client: ClientManager):
super().__init__(raw_user, client=client)
def create_user_model(
user: IUser, client: ClientManager, *, use_partial_user: Literal[True, False] = True
) -> UserModels | UserDetailedModels:
if use_partial_user and is_partial_user(user):
return PartialUser(user, client=client)
if is_me_detailed_moderator(user, config.account_id): # 自身でモデレーターが2
return MeDetailedModerator(user, client=client)
if is_me_detailed(user, config.account_id): # 自身が3
def packed_user(user: IUser, client: ClientManager) -> UserDetailedNotMe | MeDetailed:
if is_user_detailed_not_me(user):
return UserDetailedNotMe(user, client=client)
if is_me_detailed(user):
return MeDetailed(user, client=client)
if is_user_detailed_not_logined(user): # ログインしてないやつが4
return UserDetailedNotLogined(user, client=client)
if is_user_detailed_moderator(user): # 他人でモデレーター視点が5
return UserDetailedModerator(user, client=client)
if is_user_detailed(user): # 他人が6
return UserDetailed(user, client=client)
raise ValueError("Invalid user model")
UserModels = (
PartialUser
| MeDetailed[IMeDetailed]
| UserDetailedNotLogined[IUserDetailedNotLogined]
| UserDetailed[IUserDetailed]
| UserDetailedModerator
| MeDetailedModerator
)
UserDetailedModels = (
MeDetailed[IMeDetailed]
| UserDetailedNotLogined[IUserDetailedNotLogined]
| UserDetailed[IUserDetailed]
| UserDetailedModerator
| MeDetailedModerator
)

Loading…
Cancel
Save