Skip to content
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ requires-python = ">=3.10"
dependencies = [
"hishel[httpx]>=1.1.5",
"httpx>=0.28.1",
"seerapi-models>=1.0.2",
"seerapi-models>=1.2.2,<1.3.0",
"typing-extensions>=4.15.0",
]

Expand Down
31 changes: 28 additions & 3 deletions seerapi/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,23 @@
from hishel.httpx import AsyncCacheClient
from httpx import URL
from httpx._urls import QueryParams
from seerapi_models.common import ResourceRef

from seerapi._model_map import MODEL_MAP, ModelName, T_ModelInstance
from seerapi_models.common import NamedData, ResourceRef

from seerapi._model_map import (
MODEL_MAP,
ModelName,
NamedModelName,
T_ModelInstance,
T_NamedModelInstance,
)
from seerapi._models import PagedResponse, PageInfo

ResourceArg: TypeAlias = (
ModelName | type[T_ModelInstance] | ResourceRef[T_ModelInstance]
)
NamedResourceArg: TypeAlias = (
NamedModelName | type[T_NamedModelInstance] | ResourceRef[T_NamedModelInstance]
)


def _parse_url_params(url: str) -> QueryParams:
Expand Down Expand Up @@ -145,3 +154,19 @@ async def create_generator(page_info: PageInfo):
page_info = paged_response.next

return create_generator(PageInfo(offset=0, limit=10))

async def get_by_name(
self, resource_name: NamedResourceArg[T_NamedModelInstance], name: str
) -> NamedData[T_NamedModelInstance]:
res_name = self._get_resource_name(resource_name)
model_type = MODEL_MAP[res_name]
response = await self._client.get(f'/{res_name}/{name}')
response.raise_for_status()
return NamedData.model_validate(
{
'data': {
id: model_type.model_validate(item)
for id, item in response.json()['data'].items()
}
}
)
156 changes: 154 additions & 2 deletions seerapi/_client.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ from typing_extensions import Self
from hishel.httpx import AsyncCacheClient
from httpx import URL
import seerapi_models as M
from seerapi_models.common import ResourceRef
from seerapi_models.common import NamedData, ResourceRef

from seerapi._model_map import T_ModelInstance
from seerapi._model_map import T_ModelInstance, T_NamedModelInstance
from seerapi._models import PagedResponse, PageInfo

class SeerAPI:
Expand Down Expand Up @@ -575,3 +575,155 @@ class SeerAPI:
async def list(
self, resource_name: type[T_ModelInstance]
) -> AsyncGenerator[T_ModelInstance, None]: ...
@overload
async def get_by_name(
self, resource_name: Literal['battle_effect'], name: str
) -> NamedData[M.BattleEffect]: ...
@overload
async def get_by_name(
self, resource_name: Literal['battle_effect_type'], name: str
) -> NamedData[M.BattleEffectCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['pet_effect'], name: str
) -> NamedData[M.PetEffect]: ...
@overload
async def get_by_name(
self, resource_name: Literal['pet_effect_group'], name: str
) -> NamedData[M.PetEffectGroup]: ...
@overload
async def get_by_name(
self, resource_name: Literal['pet_variation'], name: str
) -> NamedData[M.VariationEffect]: ...
@overload
async def get_by_name(
self, resource_name: Literal['energy_bead'], name: str
) -> NamedData[M.EnergyBead]: ...
@overload
async def get_by_name(
self, resource_name: Literal['equip'], name: str
) -> NamedData[M.Equip]: ...
@overload
async def get_by_name(
self, resource_name: Literal['suit'], name: str
) -> NamedData[M.Suit]: ...
@overload
async def get_by_name(
self, resource_name: Literal['equip_type'], name: str
) -> NamedData[M.EquipType]: ...
@overload
async def get_by_name(
self, resource_name: Literal['soulmark_tag'], name: str
) -> NamedData[M.SoulmarkTagCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['element_type'], name: str
) -> NamedData[M.ElementType]: ...
@overload
async def get_by_name(
self, resource_name: Literal['element_type_combination'], name: str
) -> NamedData[M.TypeCombination]: ...
@overload
async def get_by_name(
self, resource_name: Literal['item'], name: str
) -> NamedData[M.Item]: ...
@overload
async def get_by_name(
self, resource_name: Literal['item_category'], name: str
) -> NamedData[M.ItemCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['gem'], name: str
) -> NamedData[M.Gem]: ...
@overload
async def get_by_name(
self, resource_name: Literal['gem_category'], name: str
) -> NamedData[M.GemCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['skill_activation_item'], name: str
) -> NamedData[M.SkillActivationItem]: ...
@overload
async def get_by_name(
self, resource_name: Literal['skill_stone'], name: str
) -> NamedData[M.SkillStone]: ...
@overload
async def get_by_name(
self, resource_name: Literal['skill_stone_category'], name: str
) -> NamedData[M.SkillStoneCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['mintmark'], name: str
) -> NamedData[M.Mintmark]: ...
@overload
async def get_by_name(
self, resource_name: Literal['ability_mintmark'], name: str
) -> NamedData[M.AbilityMintmark]: ...
@overload
async def get_by_name(
self, resource_name: Literal['skill_mintmark'], name: str
) -> NamedData[M.SkillMintmark]: ...
@overload
async def get_by_name(
self, resource_name: Literal['universal_mintmark'], name: str
) -> NamedData[M.UniversalMintmark]: ...
@overload
async def get_by_name(
self, resource_name: Literal['mintmark_class'], name: str
) -> NamedData[M.MintmarkClassCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['mintmark_type'], name: str
) -> NamedData[M.MintmarkTypeCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['pet'], name: str
) -> NamedData[M.Pet]: ...
@overload
async def get_by_name(
self, resource_name: Literal['pet_gender'], name: str
) -> NamedData[M.PetGenderCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['pet_vipbuff'], name: str
) -> NamedData[M.PetVipBuffCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['pet_mount_type'], name: str
) -> NamedData[M.PetMountTypeCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['pet_skin'], name: str
) -> NamedData[M.PetSkin]: ...
@overload
async def get_by_name(
self, resource_name: Literal['pet_archive_story_book'], name: str
) -> NamedData[M.PetArchiveStoryBook]: ...
@overload
async def get_by_name(
self, resource_name: Literal['pet_encyclopedia_entry'], name: str
) -> NamedData[M.PetEncyclopediaEntry]: ...
@overload
async def get_by_name(
self, resource_name: Literal['skill'], name: str
) -> NamedData[M.Skill]: ...
@overload
async def get_by_name(
self, resource_name: Literal['skill_hide_effect'], name: str
) -> NamedData[M.SkillHideEffect]: ...
@overload
async def get_by_name(
self, resource_name: Literal['skill_category'], name: str
) -> NamedData[M.SkillCategory]: ...
@overload
async def get_by_name(
self, resource_name: Literal['skill_effect_type_tag'], name: str
) -> NamedData[M.SkillEffectTypeTag]: ...
@overload
async def get_by_name(
self, resource_name: type[T_NamedModelInstance], name: str
) -> NamedData[T_NamedModelInstance]: ...
@overload
async def get_by_name(
self, resource_name: ResourceRef[T_NamedModelInstance], name: str
) -> NamedData[T_NamedModelInstance]: ...
65 changes: 54 additions & 11 deletions seerapi/_model_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import seerapi_models as M
from seerapi_models.common import BaseResModel

# 所有可用的模型路径名称
ModelName: TypeAlias = Literal[
NamedModelName: TypeAlias = Literal[
'battle_effect',
'battle_effect_type',
'pet_effect',
Expand All @@ -14,16 +13,13 @@
'equip',
'suit',
'equip_type',
'equip_effective_occasion',
'soulmark',
'soulmark_tag',
'element_type',
'element_type_combination',
'item',
'item_category',
'gem',
'gem_category',
'gem_generation_category',
'skill_activation_item',
'skill_stone',
'skill_stone_category',
Expand All @@ -33,30 +29,77 @@
'universal_mintmark',
'mintmark_class',
'mintmark_type',
'mintmark_rarity',
'pet',
'pet_class',
'pet_gender',
'pet_vipbuff',
'pet_mount_type',
'pet_skin',
'pet_skin_category',
'pet_archive_story_entry',
'pet_archive_story_book',
'pet_encyclopedia_entry',
'skill',
'skill_effect_type',
'skill_effect_param',
'skill_hide_effect',
'skill_category',
'skill_effect_type_tag',
]

# 所有可用的模型路径名称
ModelName: TypeAlias = Literal[
NamedModelName,
'equip_effective_occasion',
'soulmark',
'gem_generation_category',
'mintmark_rarity',
'pet_class',
'pet_skin_category',
'pet_archive_story_entry',
'skill_effect_type',
'skill_effect_param',
'eid_effect',
]

ModelInstance: TypeAlias = BaseResModel
NamedModelInstance: TypeAlias = (
M.BattleEffect
| M.BattleEffectCategory
| M.PetEffect
| M.PetEffectGroup
| M.VariationEffect
| M.EnergyBead
| M.Equip
| M.Suit
| M.EquipType
| M.SoulmarkTagCategory
| M.ElementType
| M.TypeCombination
| M.Item
| M.ItemCategory
| M.Gem
| M.GemCategory
| M.SkillActivationItem
| M.SkillStone
| M.SkillStoneCategory
| M.Mintmark
| M.AbilityMintmark
| M.SkillMintmark
| M.UniversalMintmark
| M.MintmarkClassCategory
| M.MintmarkTypeCategory
| M.Pet
| M.PetGenderCategory
| M.PetVipBuffCategory
| M.PetMountTypeCategory
| M.PetSkin
| M.PetArchiveStoryBook
| M.PetEncyclopediaEntry
| M.Skill
| M.SkillHideEffect
| M.SkillCategory
| M.SkillEffectTypeTag
)
ModelType: TypeAlias = type[ModelInstance]

T_ModelInstance = TypeVar('T_ModelInstance', bound=ModelInstance)
T_NamedModelInstance = TypeVar('T_NamedModelInstance', bound=NamedModelInstance)

MODEL_MAP: dict[ModelName, ModelType] = {
'battle_effect': M.BattleEffect,
Expand Down