from typing import List, Any
import requests
try:
from functools import cached_property
except ImportError:
from functools import lru_cache
cached_property = lambda func: property(lru_cache()(func))
class BaseScpperObject:
"""Base class for Scpper item
Attributes:
id: Wikidot id of the item to retrieve.
"""
_endpoint: str
def __init__(self, _id: int):
self.id = _id
def __repr__(self) -> str:
return f"{self.__module__}.{self.__class__.__name__}({self.id})"
def __eq__(self, other: Any) -> bool:
if not hasattr(other, "_endpoint") or not hasattr(other, "id"):
return False
return self._endpoint == other._endpoint and self.id == other.id
def get(self, name: str) -> Any:
return self._data[name]
@cached_property
def _data(self) -> Any:
"""Retrieves an item data by id.
Returns:
A dict object containing an item metadata.
Raises:
scpper.utils.NotFoundException: Item not found.
"""
data = requests.get(self._endpoint, params={"id": self.id}).json()
if "error" in data:
raise NotFoundException(data["error"])
return data
__getitem__ = __getattr__ = get
[docs]class Page(BaseScpperObject):
"""Scpper page class"""
_endpoint = "https://scpper.com/api/page"
[docs]class User(BaseScpperObject):
"""Scpper user class"""
_endpoint = "https://scpper.com/api/user"
[docs]class Scpper:
"""Scpper API wrapper class
Attributes:
site: Branch site name.
SCP Foundation (scp-wiki.net): "en"
Russian branch (scpfoundation.ru): "ru"
Korean branch (ko.scp-wiki.net): "ko"
Japanese branch (ja.scp-wiki.net): "ja"
French branch (fondationscp.wikidot.com): "fr"
Spanish branch (lafundacionscp.wikidot.com): "es"
Thai branch (scp-th.wikidot.com): "th"
Polish branch (scp-wiki.net.pl): "pl"
German branch (scp-wiki-de.wikidot.com): "de"
Chinese branch (scp-wiki-cn.wikidot.com): "cn"
Italian branch (fondazionescp.wikidot.com): "it"
SCP International (scp-int.wikidot.com): "int"
"""
def __init__(self, site: str = "en"):
self.site = site
def __repr__(self) -> str:
return "{}.{}({})".format(
self.__module__, self.__class__.__name__, repr(self.site)
)
@staticmethod
def get_page(_id: int) -> Page:
return Page(_id)
@staticmethod
def get_user(_id: int) -> User:
return User(_id)
[docs] def find_pages(self, title: str, limit: int = 50, random: bool = False) -> List[Page]:
"""Retrieves up to limit pages from the specified wiki with part of the name matching title.
Args:
title:
Search query, part of page's name (i.e. "173" will match "SCP-173", "SCP-1173", etc). Between 3 and 256 characters.
limit:
Maximum number of rows returned by the query. Limited to 50.
random:
Bool indicating whether resulting list of pages should be randomized.
False - returns limit pages ordered by (kind of) relevance, descending (default)
True - returns random selection of limit pages from the original query.
Returns:
A list object containing all found pages.
Raises:
ValueError: Title must be between 3 and 256 characters long.
"""
if len(title) < 3 or len(title) > 256:
raise ValueError("Title must be between 3 and 256 characters long")
pages = requests.get(
"https://scpper.com/api/find-pages",
params={
"site": self.site,
"title": title,
"limit": limit,
"random": int(random),
},
).json()["pages"]
return [self.get_page(page["id"]) for page in pages]
[docs] def find_users(self, name: str, limit: int = 50) -> List[User]:
"""Retrieves up to limit users from the with part of the name matching name.
Args:
name:
Search query, part of user's name (i.e. "cle" will match "Dr Clef", "Agent MacLeod", etc). Between 3 and 256 characters.
limit:
Maximum number of rows returned by the query. Limited to 50.
Returns:
A list object containing all found users.
Raises:
ValueError: Name must be between 3 and 256 characters long.
"""
if len(name) < 3 or len(name) > 256:
raise ValueError("Name must be between 3 and 256 characters long")
users = requests.get(
"https://scpper.com/api/find-users",
params={
"site": self.site,
"name": name,
"limit": limit},
).json()["users"]
return [self.get_user(user["id"]) for user in users]
class NotFoundException(Exception):
pass