-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit dcd09ee
Showing
13 changed files
with
534 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
__pycache__ | ||
venv | ||
build | ||
mihomo.egg-info | ||
*.ipynb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Copyright 2023 KT | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# mihomo | ||
A simple Python Pydantic model (type hint and autocompletion support) for Honkai: Star Rail parsed data from the Mihomo API. | ||
|
||
API url: https://api.mihomo.me/sr_info_parsed/{UID}?lang={LANG} | ||
|
||
## Installation | ||
``` | ||
pip install -U git+https://github.com/KT-Yeh/mihomo.git | ||
``` | ||
|
||
## Usage | ||
An example for https://api.mihomo.me/sr_info_parsed/800333171?lang=en | ||
|
||
```py | ||
import asyncio | ||
|
||
from mihomo import MihomoAPI, Language | ||
|
||
client = MihomoAPI(language=Language.EN) | ||
|
||
async def main(): | ||
data = await client.fetch_user(800333171) | ||
|
||
print(f"Name: {data.player.name}") | ||
print(f"Level: {data.player.level}") | ||
print(f"Signature: {data.player.signature}") | ||
print(f"Achievements: {data.player_details.achievements}") | ||
print(f"Characters count: {data.player_details.characters}") | ||
print(f"Profile picture url: {client.get_icon_url(data.player.icon)}") | ||
for character in data.characters: | ||
print("-----------") | ||
print(f"Name: {character.name}") | ||
print(f"rarity: {character.rarity}") | ||
print(f"Level: {character.level}") | ||
print(f"Avatar url: {client.get_icon_url(character.icon)}") | ||
print(f"Preview url: {client.get_icon_url(character.preview)}") | ||
print(f"portrait url: {client.get_icon_url(character.portrait)}") | ||
|
||
asyncio.run(main()) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .client import * | ||
from .errors import * | ||
from .models import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import typing | ||
from enum import Enum | ||
|
||
import aiohttp | ||
|
||
from .errors import HttpRequestError | ||
from .models import StarrailInfoParsed | ||
from .tools import remove_empty_dict, replace_trailblazer_name | ||
|
||
|
||
class Language(Enum): | ||
CHT = "cht" | ||
DE = "de" | ||
EN = "en" | ||
ES = "es" | ||
FR = "fr" | ||
ID = "id" | ||
JP = "jp" | ||
KR = "kr" | ||
PT = "pt" | ||
RU = "ru" | ||
TH = "th" | ||
VI = "vi" | ||
|
||
|
||
class MihomoAPI: | ||
""" | ||
Represents an client for Mihomo API. | ||
Args: | ||
language (Language, optional): | ||
The language to use for API responses.Defaults to Language.CHT. | ||
Attributes: | ||
- BASE_URL (str): The base URL of the API. | ||
- ASSET_URL (str): The base URL for the asset files. | ||
""" | ||
|
||
BASE_URL: typing.Final[str] = "https://api.mihomo.me/sr_info_parsed" | ||
ASSET_URL: typing.Final[str] = "https://raw.githubusercontent.com/Mar-7th/StarRailRes/master" | ||
|
||
def __init__(self, language: Language = Language.CHT): | ||
self.lang = language | ||
|
||
async def request( | ||
self, | ||
uid: int | str, | ||
language: Language, | ||
) -> typing.Any: | ||
""" | ||
Makes an HTTP request to the API. | ||
Args: | ||
- uid (int | str): The user ID. | ||
- language (Language): The language to use for the API response. | ||
Returns: | ||
typing.Any: The response from the API. | ||
Raises: | ||
HttpRequestError: If the HTTP request fails. | ||
""" | ||
url = self.BASE_URL + "/" + str(uid) | ||
params = {"lang": language.value} | ||
async with aiohttp.ClientSession() as session: | ||
async with session.get(url, params=params) as response: | ||
if response.status == 200: | ||
return await response.json(encoding="utf-8") | ||
else: | ||
raise HttpRequestError(response.status, str(response.reason)) | ||
|
||
async def fetch_user(self, uid: int) -> StarrailInfoParsed: | ||
""" | ||
Fetches user data from the API. | ||
Args: | ||
uid (int): The user ID. | ||
Returns: | ||
StarrailInfoParsed: The parsed user data from mihomo API. | ||
""" | ||
data = await self.request(uid, self.lang) | ||
data = remove_empty_dict(data) | ||
data = StarrailInfoParsed.parse_obj(data) | ||
data = replace_trailblazer_name(data) | ||
return data | ||
|
||
def get_icon_url(self, icon: str) -> str: | ||
""" | ||
Gets the asset url for the given icon. | ||
Args: | ||
icon (str): The icon name. | ||
Returns: | ||
str: The asset url for the icon. | ||
""" | ||
return self.ASSET_URL + "/" + icon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
class HttpRequestError(Exception): | ||
"""Http request failed""" | ||
|
||
status: int = 0 | ||
reason: str = "" | ||
message: str = "" | ||
|
||
def __init__( | ||
self, | ||
status: int, | ||
reason: str, | ||
message: str | None = None, | ||
*args: object, | ||
) -> None: | ||
if not message: | ||
message = f"[{status}] {reason}" | ||
self.status = status | ||
self.reason = reason | ||
self.message = message | ||
super().__init__(message, *args) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from .base import * | ||
from .character import * | ||
from .equipment import * | ||
from .player import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from pydantic import BaseModel, Field | ||
|
||
from .character import Character | ||
from .player import Player, PlayerSpaceInfo | ||
|
||
|
||
class StarrailInfoParsed(BaseModel): | ||
""" | ||
Mihomo parsed data | ||
Attributes: | ||
- player (`Player`): The player's basic info. | ||
- player_details (`PlayerSpaceInfo`): The player's details. | ||
- characters (list[`Character`]): The list of characters. | ||
""" | ||
|
||
player: Player | ||
"""Player's basic info""" | ||
player_details: PlayerSpaceInfo = Field(..., alias="PlayerSpaceInfo") | ||
"""Player's details""" | ||
characters: list[Character] | ||
"""The list of characters""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
from typing import Any | ||
|
||
from pydantic import BaseModel, Field, root_validator | ||
|
||
from .equipment import LightCone, Relic, RelicSet | ||
|
||
|
||
class EidolonIcon(BaseModel): | ||
""" | ||
Represents an Eidolon icon. | ||
Attributes: | ||
- icon (`str`): The eidolon icon. | ||
- unlock (`bool`): Indicates if the eidolon is unlocked. | ||
""" | ||
|
||
icon: str | ||
"""The eidolon icon""" | ||
unlock: bool | ||
"""Indicates if the eidolon is unlocked""" | ||
|
||
|
||
class Trace(BaseModel): | ||
""" | ||
Represents a character's skill trace. | ||
Attributes: | ||
- name (`str`): The name of the trace. | ||
- level (`int`): The level of the trace. | ||
- type (`str`): The type of the trace. | ||
- icon (`str`): The trace icon. | ||
""" | ||
|
||
name: str | ||
"""The name of the trace""" | ||
level: int | ||
"""The level of the trace""" | ||
type: str | ||
"""The type of the trace""" | ||
icon: str | ||
"""The trace icon""" | ||
|
||
|
||
class Stat(BaseModel): | ||
""" | ||
Represents a character's stat. | ||
Attributes: | ||
- name (`str`): The name of the stat. | ||
- base (`str`): The base value of the stat. | ||
- addition (`str` | `None`): The additional value of the stat, or None if not applicable. | ||
- icon (`str`): The stat icon. | ||
""" | ||
|
||
name: str | ||
"""The name of the stat""" | ||
base: str | ||
"""The base value of the stat""" | ||
addition: str | None = None | ||
"""The additional value of the stat""" | ||
icon: str | ||
"""The stat icon""" | ||
|
||
|
||
class Character(BaseModel): | ||
""" | ||
Represents a character. | ||
Attributes: | ||
- Basic info: | ||
- id (`str`): The character's ID. | ||
- name (`str`): The character's name. | ||
- rarity (`int`): The character's rarity. | ||
- level (`int`): The character's level. | ||
- Eidolon | ||
- eidolon (`int`): The character's eidolon rank. | ||
- eidolon_text (`str`): The text representation of the eidolon. | ||
- eidolon_icons (list[`EidolonIcon`]): The list of eidolon icons. | ||
- Image | ||
- icon (`str`): The character avatar image | ||
- preview (`str`): The character's preview image. | ||
- portrait (`str`): The character's portrait image. | ||
- Combat type | ||
- path (`str`): The character's path. | ||
- path_icon (`str`): The character's path icon. | ||
- element (`str`): The character's element. | ||
- element_icon (`str`): The character's element icon. | ||
- color (`str`): The character's element color. | ||
- Equipment | ||
- traces (list[`Trace`]): The list of character's skill traces. | ||
- light_cone (`LightCone` | `None`): The character's light cone (weapon), or None if not applicable. | ||
- relics (list[`Relic`] | `None`): The list of character's relics, or None if not applicable. | ||
- relic_set (list[`RelicSet`] | `None`): The list of character's relic sets, or None if not applicable. | ||
- stats (list[`Stat`]): The list of character's stats. | ||
""" | ||
|
||
id: str | ||
"""Character's ID""" | ||
name: str | ||
"""Character's name""" | ||
rarity: int | ||
"""Character's rarity""" | ||
level: int | ||
"""Character's level""" | ||
|
||
eidolon: int = Field(..., alias="rank") | ||
"""Character's eidolon rank""" | ||
eidolon_text: str = Field(..., alias="rank_text") | ||
"""The text representation of the eidolon""" | ||
eidolon_icons: list[EidolonIcon] = Field(..., alias="rank_icons") | ||
"""The list of eidolon icons""" | ||
|
||
preview: str | ||
"""Character preview image""" | ||
portrait: str | ||
"""Character portrait image""" | ||
|
||
path: str | ||
"""Character's path""" | ||
path_icon: str | ||
"""Character's path icon""" | ||
|
||
element: str | ||
"""Character's element""" | ||
element_icon: str | ||
"""Character's element icon""" | ||
|
||
color: str | ||
"""Character's element color""" | ||
|
||
traces: list[Trace] = Field(..., alias="skill") | ||
"""The list of character's skill traces""" | ||
light_cone: LightCone | None = None | ||
"""Character's light cone (weapon)""" | ||
relics: list[Relic] | None = Field(None, alias="relic") | ||
"""The list of character's relics""" | ||
relic_set: list[RelicSet] | None = None | ||
"""The list of character's relic sets""" | ||
stats: list[Stat] = Field(..., alias="property") | ||
"""The list of character's stats""" | ||
|
||
@root_validator(pre=True) | ||
def dict_to_list(cls, data: dict[str, Any]): | ||
# The keys of the original dict is not necessary, so remove them here. | ||
if data.get("relic") is not None: | ||
data["relic"] = list(data["relic"].values()) | ||
return data | ||
|
||
@property | ||
def icon(self) -> str: | ||
"""Character avatar image""" | ||
return f"icon/character/{self.id}.png" |
Oops, something went wrong.