mirror of
https://github.com/bohd4nx/FragmentAPI.git
synced 2026-07-25 06:14:29 +00:00
feat: implement client.call() method for raw Fragment API requests; add example and unit tests
This commit is contained in:
+41
-2
@@ -1,5 +1,7 @@
|
||||
import json
|
||||
from typing import cast
|
||||
from typing import Any, cast
|
||||
|
||||
import httpx
|
||||
|
||||
from pyfragment.methods.giveaway_premium import giveaway_premium
|
||||
from pyfragment.methods.giveaway_stars import giveaway_stars
|
||||
@@ -14,8 +16,15 @@ from pyfragment.types import (
|
||||
StarsResult,
|
||||
WalletInfo,
|
||||
)
|
||||
from pyfragment.types.constants import DEFAULT_TIMEOUT, REQUIRED_COOKIE_KEYS, SUPPORTED_WALLET_VERSIONS, WalletVersion
|
||||
from pyfragment.types.constants import (
|
||||
DEFAULT_TIMEOUT,
|
||||
FRAGMENT_BASE_URL,
|
||||
REQUIRED_COOKIE_KEYS,
|
||||
SUPPORTED_WALLET_VERSIONS,
|
||||
WalletVersion,
|
||||
)
|
||||
from pyfragment.types.results import PremiumGiveawayResult, StarsGiveawayResult
|
||||
from pyfragment.utils.http import fragment_request, get_fragment_hash, make_headers
|
||||
from pyfragment.utils.wallet import get_wallet_info
|
||||
|
||||
|
||||
@@ -187,3 +196,33 @@ class FragmentClient:
|
||||
``winners``, and ``amount``.
|
||||
"""
|
||||
return await giveaway_premium(self, channel, winners, months)
|
||||
|
||||
async def call(
|
||||
self, method: str, data: dict[str, Any] | None = None, *, page_url: str = FRAGMENT_BASE_URL
|
||||
) -> dict[str, Any]:
|
||||
"""Send a raw request to the Fragment API.
|
||||
|
||||
Useful for accessing undocumented or future Fragment API methods
|
||||
without waiting for a library update.
|
||||
|
||||
Args:
|
||||
method: Fragment API method name, e.g. ``"searchPremiumGiftRecipient"``.
|
||||
data: Additional form-data fields to include in the request body.
|
||||
page_url: Fragment page URL used to derive the API hash and headers.
|
||||
Defaults to ``FRAGMENT_BASE_URL`` (``"https://fragment.com"``).
|
||||
|
||||
Returns:
|
||||
Raw parsed JSON response as a dict.
|
||||
|
||||
Example::
|
||||
|
||||
result = await client.call(
|
||||
"searchPremiumGiftRecipient",
|
||||
{"query": "@username", "months": 3},
|
||||
page_url="https://fragment.com/premium/gift",
|
||||
)
|
||||
"""
|
||||
headers = make_headers(page_url)
|
||||
async with httpx.AsyncClient(cookies=self.cookies, timeout=self.timeout) as session:
|
||||
fragment_hash = await get_fragment_hash(self.cookies, headers, page_url, self.timeout)
|
||||
return await fragment_request(session, fragment_hash, headers, {"method": method, **(data or {})})
|
||||
|
||||
@@ -20,11 +20,12 @@ DEFAULT_TIMEOUT: float = 30.0
|
||||
REQUIRED_COOKIE_KEYS: tuple[str, ...] = ("stel_ssid", "stel_dt", "stel_token", "stel_ton_token")
|
||||
|
||||
# Fragment page URLs
|
||||
STARS_PAGE: str = "https://fragment.com/stars/buy"
|
||||
STARS_GIVEAWAY_PAGE: str = "https://fragment.com/stars/giveaway"
|
||||
PREMIUM_PAGE: str = "https://fragment.com/premium/gift"
|
||||
PREMIUM_GIVEAWAY_PAGE: str = "https://fragment.com/premium/giveaway"
|
||||
TON_PAGE: str = "https://fragment.com/ads/topup"
|
||||
FRAGMENT_BASE_URL: str = "https://fragment.com"
|
||||
STARS_PAGE: str = f"{FRAGMENT_BASE_URL}/stars/buy"
|
||||
STARS_GIVEAWAY_PAGE: str = f"{FRAGMENT_BASE_URL}/stars/giveaway"
|
||||
PREMIUM_PAGE: str = f"{FRAGMENT_BASE_URL}/premium/gift"
|
||||
PREMIUM_GIVEAWAY_PAGE: str = f"{FRAGMENT_BASE_URL}/premium/giveaway"
|
||||
TON_PAGE: str = f"{FRAGMENT_BASE_URL}/ads/topup"
|
||||
|
||||
# Tonkeeper device fingerprint — serialized once, reused in every tx_data payload.
|
||||
DEVICE: str = json.dumps(
|
||||
@@ -47,7 +48,7 @@ BASE_HEADERS: dict[str, str] = {
|
||||
"accept": "application/json, text/javascript, */*; q=0.01",
|
||||
"accept-language": "en-US,en;q=0.9,uk;q=0.8,ru;q=0.7",
|
||||
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"origin": "https://fragment.com",
|
||||
"origin": FRAGMENT_BASE_URL,
|
||||
"priority": "u=1, i",
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
|
||||
@@ -4,10 +4,10 @@ from typing import Any
|
||||
import httpx
|
||||
|
||||
from pyfragment.types import FragmentPageError, ParseError, VerificationError
|
||||
from pyfragment.types.constants import BASE_HEADERS, DEFAULT_TIMEOUT
|
||||
from pyfragment.types.constants import BASE_HEADERS, DEFAULT_TIMEOUT, FRAGMENT_BASE_URL
|
||||
|
||||
|
||||
def make_headers(page_url: str) -> dict[str, str]:
|
||||
def make_headers(page_url: str = FRAGMENT_BASE_URL) -> dict[str, str]:
|
||||
return {**BASE_HEADERS, "referer": page_url, "x-aj-referer": page_url}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ async def get_fragment_hash(
|
||||
page_headers.update(
|
||||
{
|
||||
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
"referer": "https://fragment.com/",
|
||||
"referer": f"{FRAGMENT_BASE_URL}/",
|
||||
"sec-fetch-dest": "document",
|
||||
"sec-fetch-mode": "navigate",
|
||||
"upgrade-insecure-requests": "1",
|
||||
@@ -105,7 +105,7 @@ async def fragment_request(
|
||||
Parsed API response as a dict.
|
||||
"""
|
||||
resp = await session.post(
|
||||
f"https://fragment.com/api?hash={fragment_hash}",
|
||||
f"{FRAGMENT_BASE_URL}/api?hash={fragment_hash}",
|
||||
headers=headers,
|
||||
data=data,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user