lots
This commit is contained in:
@@ -67,7 +67,9 @@ class BaseExternalService:
|
||||
logger.error(f"Failed to parse JSON response: {e}")
|
||||
return raw_response
|
||||
return raw_response
|
||||
|
||||
except aiohttp.ClientResponseError as e:
|
||||
logger.error(f"Request failed: {e}")
|
||||
raise
|
||||
except aiohttp.ClientError as e:
|
||||
logger.error(f"Request failed: {e}")
|
||||
raise
|
||||
|
@@ -3,6 +3,9 @@ from datetime import datetime, timedelta
|
||||
import csv
|
||||
import io
|
||||
from app.services.external_api.base_external_service import BaseExternalService
|
||||
import aiohttp
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class TCGCSVService(BaseExternalService):
|
||||
def __init__(self):
|
||||
@@ -16,7 +19,14 @@ class TCGCSVService(BaseExternalService):
|
||||
async def get_products_and_prices(self, game_id: str, group_id: int) -> str:
|
||||
"""Fetch products and prices for a specific group from TCGCSV API"""
|
||||
endpoint = f"tcgplayer/{game_id}/{group_id}/ProductsAndPrices.csv"
|
||||
return await self._make_request("GET", endpoint, headers={"Accept": "text/csv"})
|
||||
try:
|
||||
return await self._make_request("GET", endpoint, headers={"Accept": "text/csv"})
|
||||
except aiohttp.ClientResponseError as e:
|
||||
if e.status == 403:
|
||||
logger.error(f"Request failed: {e}")
|
||||
return None
|
||||
else:
|
||||
raise
|
||||
|
||||
async def get_categories(self) -> Dict[str, Any]:
|
||||
"""Fetch all categories from TCGCSV API"""
|
||||
@@ -26,7 +36,14 @@ class TCGCSVService(BaseExternalService):
|
||||
async def get_archived_prices_for_date(self, date_str: str) -> bytes:
|
||||
"""Fetch archived prices from TCGCSV API"""
|
||||
endpoint = f"archive/tcgplayer/prices-{date_str}.ppmd.7z"
|
||||
return await self._make_request("GET", endpoint, binary=True)
|
||||
try:
|
||||
return await self._make_request("GET", endpoint, binary=True)
|
||||
except aiohttp.ClientResponseError as e:
|
||||
if e.status == 403:
|
||||
logger.error(f"Request failed: {e}")
|
||||
return None
|
||||
else:
|
||||
raise
|
||||
|
||||
async def get_tcgcsv_date_range(self, start_date: datetime, end_date: datetime) -> List[datetime]:
|
||||
"""Get a date range for a given start and end date"""
|
||||
|
@@ -10,6 +10,8 @@ class BaseTCGPlayerService(BaseExternalService):
|
||||
STORE_BASE_URL = "https://store.tcgplayer.com"
|
||||
LOGIN_ENDPOINT = "/oauth/login"
|
||||
PRICING_ENDPOINT = "/Admin/Pricing"
|
||||
MP_SEARCH_URL = "https://mp-search-api.tcgplayer.com/v1"
|
||||
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(base_url=self.STORE_BASE_URL)
|
||||
|
@@ -407,8 +407,8 @@ class OrderManagementService(BaseTCGPlayerService):
|
||||
('extended_price', 'extendedPrice'),
|
||||
('quantity', 'quantity'),
|
||||
('url', 'url'),
|
||||
('tcgplayer_product_id', 'productId'),
|
||||
('tcgplayer_sku_id', 'skuId')
|
||||
('product_id', 'productId'),
|
||||
('sku_id', 'skuId')
|
||||
]
|
||||
|
||||
for db_field, api_field in product_fields_to_compare:
|
||||
|
@@ -0,0 +1,54 @@
|
||||
from app.services.external_api.tcgplayer.base_tcgplayer_service import BaseTCGPlayerService
|
||||
from sqlalchemy.orm import Session
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class TCGPlayerMarketDataInput:
|
||||
product_id: str
|
||||
mpfev: str
|
||||
condition: str
|
||||
language: str
|
||||
printing: str
|
||||
quantity: int
|
||||
|
||||
class TCGPlayerMarketDataService(BaseTCGPlayerService):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
async def get_active_listings(self, db: Session, input: TCGPlayerMarketDataInput):
|
||||
listings_endpoint = f"{self.MP_SEARCH_URL}/product/{input.product_id}/listings?mpfev={input.mpfev}"
|
||||
"""
|
||||
curl 'https://mp-search-api.tcgplayer.com/v1/product/631066/listings?mpfev=3816' \
|
||||
-H 'accept: application/json, text/plain, */*' \
|
||||
-H 'accept-language: en-US,en;q=0.5' \
|
||||
-H 'content-type: application/json' \
|
||||
-b 'tracking-preferences={%22version%22:1%2C%22destinations%22:{%22Actions%20Amplitude%22:false%2C%22AdWords%22:false%2C%22Google%20AdWords%20New%22:false%2C%22Google%20Enhanced%20Conversions%22:false%2C%22Google%20Tag%20Manager%22:false%2C%22Impact%20Partnership%20Cloud%22:false%2C%22Optimizely%22:false}%2C%22custom%22:{%22advertising%22:false%2C%22functional%22:false%2C%22marketingAndAnalytics%22:false}}; tcg-uuid=4321c3a3-bdc0-4a3f-952f-ada250ea91ab; product-display-settings=sort=price+shipping&size=10; setting=CD=US&M=1; brwsr=f9b5ab04-479f-11f0-9996-95b462f705de; TCG_VisitorKey=1cfd1431-fc5d-461b-9fb3-61de387f3342; SellerProximity=ZipCode=&MaxSellerDistance=1000&IsActive=false; OAuthLoginSessionId=766a573b-d2ba-4285-8eae-c79b5c8a877c; TCGAuthTicket_Production=3C334E06A27B20FDD326A6C20C7FFDEFECD7EDB73BBE7E2A072607D3417CFDC3B1A12EDA8F5B4F393380FA2CA8FCF596476F2BEC3B54FDE788D57A05745D8820DF0897F3B673BACD6487BDA6CC0780896CB382DCFAB9AFC90B747ED5561CE5B7B8E122D0815203F93DE6EDB73894CE9CD20D6090; BuyerRevalidationKey=; ASP.NET_SessionId=s04smsk3opzinl2tl31x042r; __RequestVerificationToken_L2FkbWlu0=TnVB3O7LFL0SbCOd2ULkhadaytHVM8uXJqi8b-27w6WdPQ3QU9P76z92HmVS-i4K0SjbPDbvGe8grkme7l4m6fgetX01; LastSeller=e576ed4c; StoreSaveForLater_PRODUCTION=SFLK=4db1ce3215c84eaca7439f889cd70b79&Ignore=false; SearchCriteria=M=1&WantVerifiedSellers=False&WantDirect=False&WantSellersInCart=False&WantWPNSellers=False; SearchSortSettings=M=1&ProductSortOption=Sales&ProductSortDesc=False&PriceSortOption=Shipping&ProductResultDisplay=grid; tcg-segment-session=1749821401966%257C1749822225413' \
|
||||
-H 'origin: https://www.tcgplayer.com' \
|
||||
-H 'priority: u=1, i' \
|
||||
-H 'referer: https://www.tcgplayer.com/' \
|
||||
-H 'sec-ch-ua: "Brave";v="137", "Chromium";v="137", "Not/A)Brand";v="24"' \
|
||||
-H 'sec-ch-ua-mobile: ?0' \
|
||||
-H 'sec-ch-ua-platform: "Linux"' \
|
||||
-H 'sec-fetch-dest: empty' \
|
||||
-H 'sec-fetch-mode: cors' \
|
||||
-H 'sec-fetch-site: same-site' \
|
||||
-H 'sec-gpc: 1' \
|
||||
-H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36' \
|
||||
--data-raw '{"filters":{"term":{"sellerStatus":"Live","channelId":0,"language":["English"],"condition":["Near Mint"],"printing":["Foil"]},"range":{"quantity":{"gte":2}},"exclude":{"channelExclusion":0}},"from":0,"size":10,"sort":{"field":"price+shipping","order":"asc"},"context":{"shippingCountry":"US","cart":{}},"aggregations":["listingType"]}'
|
||||
"""
|
||||
headers = {
|
||||
'accept': 'application/json, text/plain, */*',
|
||||
'accept-language': 'en-US,en;q=0.5',
|
||||
'content-type': 'application/json',
|
||||
'origin': 'https://www.tcgplayer.com',
|
||||
'priority': 'u=1, i',
|
||||
'referer': 'https://www.tcgplayer.com/',
|
||||
'sec-ch-ua': '"Brave";v="137", "Chromium";v="137", "Not/A)Brand";v="24"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-platform': 'Linux',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-site': 'same-site',
|
||||
'sec-gpc': '1',
|
||||
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'
|
||||
}
|
Reference in New Issue
Block a user