mirror of
https://github.com/hwchase17/langchain
synced 2024-11-06 03:20:49 +00:00
165 lines
5.7 KiB
Python
165 lines
5.7 KiB
Python
|
"""Util that calls Steam-WebAPI."""
|
||
|
|
||
|
from typing import Any, List
|
||
|
|
||
|
from langchain_core.pydantic_v1 import BaseModel, Extra, root_validator
|
||
|
|
||
|
|
||
|
class SteamWebAPIWrapper(BaseModel):
|
||
|
"""Wrapper for Steam API."""
|
||
|
|
||
|
steam: Any # for python-steam-api
|
||
|
|
||
|
from langchain_community.tools.steam.prompt import (
|
||
|
STEAM_GET_GAMES_DETAILS,
|
||
|
STEAM_GET_RECOMMENDED_GAMES,
|
||
|
)
|
||
|
|
||
|
# operations: a list of dictionaries, each representing a specific operation that
|
||
|
# can be performed with the API
|
||
|
operations: List[dict] = [
|
||
|
{
|
||
|
"mode": "get_game_details",
|
||
|
"name": "Get Game Details",
|
||
|
"description": STEAM_GET_GAMES_DETAILS,
|
||
|
},
|
||
|
{
|
||
|
"mode": "get_recommended_games",
|
||
|
"name": "Get Recommended Games",
|
||
|
"description": STEAM_GET_RECOMMENDED_GAMES,
|
||
|
},
|
||
|
]
|
||
|
|
||
|
class Config:
|
||
|
"""Configuration for this pydantic object."""
|
||
|
|
||
|
extra = Extra.forbid
|
||
|
|
||
|
def get_operations(self) -> List[dict]:
|
||
|
"""Return a list of operations."""
|
||
|
return self.operations
|
||
|
|
||
|
@root_validator
|
||
|
def validate_environment(cls, values: dict) -> dict:
|
||
|
"""Validate api key and python package has been configured."""
|
||
|
|
||
|
# check if the python package is installed
|
||
|
try:
|
||
|
from steam import Steam
|
||
|
except ImportError:
|
||
|
raise ImportError("python-steam-api library is not installed. ")
|
||
|
|
||
|
try:
|
||
|
from decouple import config
|
||
|
except ImportError:
|
||
|
raise ImportError("decouple library is not installed. ")
|
||
|
|
||
|
# initialize the steam attribute for python-steam-api usage
|
||
|
KEY = config("STEAM_KEY")
|
||
|
steam = Steam(KEY)
|
||
|
values["steam"] = steam
|
||
|
return values
|
||
|
|
||
|
def parse_to_str(self, details: dict) -> str: # For later parsing
|
||
|
"""Parse the details result."""
|
||
|
result = ""
|
||
|
for key, value in details.items():
|
||
|
result += "The " + str(key) + " is: " + str(value) + "\n"
|
||
|
return result
|
||
|
|
||
|
def get_id_link_price(self, games: dict) -> dict:
|
||
|
"""The response may contain more than one game, so we need to choose the right
|
||
|
one and return the id."""
|
||
|
|
||
|
game_info = {}
|
||
|
for app in games["apps"]:
|
||
|
game_info["id"] = app["id"]
|
||
|
game_info["link"] = app["link"]
|
||
|
game_info["price"] = app["price"]
|
||
|
break
|
||
|
return game_info
|
||
|
|
||
|
def remove_html_tags(self, html_string: str) -> str:
|
||
|
from bs4 import BeautifulSoup
|
||
|
|
||
|
soup = BeautifulSoup(html_string, "html.parser")
|
||
|
return soup.get_text()
|
||
|
|
||
|
def details_of_games(self, name: str) -> str:
|
||
|
games = self.steam.apps.search_games(name)
|
||
|
info_partOne_dict = self.get_id_link_price(games)
|
||
|
info_partOne = self.parse_to_str(info_partOne_dict)
|
||
|
id = str(info_partOne_dict.get("id"))
|
||
|
info_dict = self.steam.apps.get_app_details(id)
|
||
|
data = info_dict.get(id).get("data")
|
||
|
detailed_description = data.get("detailed_description")
|
||
|
|
||
|
# detailed_description contains <li> <br> some other html tags, so we need to
|
||
|
# remove them
|
||
|
detailed_description = self.remove_html_tags(detailed_description)
|
||
|
supported_languages = info_dict.get(id).get("data").get("supported_languages")
|
||
|
info_partTwo = (
|
||
|
"The summary of the game is: "
|
||
|
+ detailed_description
|
||
|
+ "\n"
|
||
|
+ "The supported languages of the game are: "
|
||
|
+ supported_languages
|
||
|
+ "\n"
|
||
|
)
|
||
|
info = info_partOne + info_partTwo
|
||
|
return info
|
||
|
|
||
|
def get_steam_id(self, name: str) -> str:
|
||
|
user = self.steam.users.search_user(name)
|
||
|
steam_id = user["player"]["steamid"]
|
||
|
return steam_id
|
||
|
|
||
|
def get_users_games(self, steam_id: str) -> List[str]:
|
||
|
return self.steam.users.get_owned_games(steam_id, False, False)
|
||
|
|
||
|
def recommended_games(self, steam_id: str) -> str:
|
||
|
try:
|
||
|
import steamspypi
|
||
|
except ImportError:
|
||
|
raise ImportError("steamspypi library is not installed.")
|
||
|
users_games = self.get_users_games(steam_id)
|
||
|
result = {} # type: ignore
|
||
|
most_popular_genre = ""
|
||
|
most_popular_genre_count = 0
|
||
|
for game in users_games["games"]: # type: ignore
|
||
|
appid = game["appid"]
|
||
|
data_request = {"request": "appdetails", "appid": appid}
|
||
|
genreStore = steamspypi.download(data_request)
|
||
|
genreList = genreStore.get("genre", "").split(", ")
|
||
|
|
||
|
for genre in genreList:
|
||
|
if genre in result:
|
||
|
result[genre] += 1
|
||
|
else:
|
||
|
result[genre] = 1
|
||
|
if result[genre] > most_popular_genre_count:
|
||
|
most_popular_genre_count = result[genre]
|
||
|
most_popular_genre = genre
|
||
|
|
||
|
data_request = dict()
|
||
|
data_request["request"] = "genre"
|
||
|
data_request["genre"] = most_popular_genre
|
||
|
data = steamspypi.download(data_request)
|
||
|
sorted_data = sorted(
|
||
|
data.values(), key=lambda x: x.get("average_forever", 0), reverse=True
|
||
|
)
|
||
|
owned_games = [game["appid"] for game in users_games["games"]] # type: ignore
|
||
|
remaining_games = [
|
||
|
game for game in sorted_data if game["appid"] not in owned_games
|
||
|
]
|
||
|
top_5_popular_not_owned = [game["name"] for game in remaining_games[:5]]
|
||
|
return str(top_5_popular_not_owned)
|
||
|
|
||
|
def run(self, mode: str, game: str) -> str:
|
||
|
if mode == "get_games_details":
|
||
|
return self.details_of_games(game)
|
||
|
elif mode == "get_recommended_games":
|
||
|
return self.recommended_games(game)
|
||
|
else:
|
||
|
raise ValueError(f"Invalid mode {mode} for Steam API.")
|