diff --git a/.gitignore b/.gitignore index e81ab8f..fbdf06e 100644 --- a/.gitignore +++ b/.gitignore @@ -173,4 +173,5 @@ cython_debug/ temp/ .DS_Store *.db-journal -cookies/ \ No newline at end of file +cookies/ +alembic/versions/* \ No newline at end of file diff --git a/app/db/models.py b/app/db/models.py index 9cdce96..8530163 100644 --- a/app/db/models.py +++ b/app/db/models.py @@ -328,6 +328,41 @@ class TCGPlayerGroups(Base): modified_on = Column(String) category_id = Column(Integer) +class Orders(Base): + __tablename__ = 'orders' + + id = Column(String, primary_key=True) + order_id = Column(String, unique=True) + buyer_name = Column(String) + recipient_name = Column(String) + recipient_address_one = Column(String) + recipient_address_two = Column(String) + recipient_city = Column(String) + recipient_state = Column(String) + recipient_zip = Column(String) + recipient_country = Column(String) + order_date = Column(String) + status = Column(String) + num_products = Column(Integer) + num_cards = Column(Integer) + product_amount = Column(Float) + shipping_amount = Column(Float) + gross_amount = Column(Float) + fee_amount = Column(Float) + net_amount = Column(Float) + direct_fee_amount = Column(Float) + date_created = Column(DateTime, default=datetime.now) + date_modified = Column(DateTime, default=datetime.now, onupdate=datetime.now) + +class OrderProducts(Base): + __tablename__ = 'order_products' + + id = Column(String, primary_key=True) + order_id = Column(String, ForeignKey('orders.id')) + product_id = Column(String, ForeignKey('products.id')) + quantity = Column(Integer) + unit_price = Column(Float) + # enums class RarityEnum(str, Enum): diff --git a/app/dependencies.py b/app/dependencies.py index ba4090b..3fbce88 100644 --- a/app/dependencies.py +++ b/app/dependencies.py @@ -10,6 +10,7 @@ from app.services.product import ProductService from app.services.inventory import InventoryService from app.services.task import TaskService from app.services.storage import StorageService +from app.services.tcgplayer_api import TCGPlayerAPIService from app.db.database import get_db from app.schemas.file import CreateFileRequest from app.schemas.box import CreateBoxRequest, UpdateBoxRequest, CreateOpenBoxRequest @@ -18,6 +19,10 @@ from app.schemas.box import CreateBoxRequest, UpdateBoxRequest, CreateOpenBoxReq DB = Annotated[Session, Depends(get_db)] # Base Services (no dependencies besides DB) +def get_tcgplayer_api_service(db: DB) -> TCGPlayerAPIService: + """TCGPlayerAPIService with only database dependency""" + return TCGPlayerAPIService(db) + def get_file_service(db: DB) -> FileService: """FileService with only database dependency""" return FileService(db) diff --git a/app/routes/routes.py b/app/routes/routes.py index 0c79bef..d040039 100644 --- a/app/routes/routes.py +++ b/app/routes/routes.py @@ -25,10 +25,12 @@ from app.schemas.box import ( CreateOpenBoxResponse, OpenBoxSchema ) +from app.schemas.orders import ProcessOrdersResponse from app.services.file import FileService from app.services.box import BoxService from app.services.task import TaskService from app.services.pricing import PricingService +from app.services.tcgplayer_api import TCGPlayerAPIService from app.dependencies import ( get_file_service, get_box_service, @@ -37,7 +39,8 @@ from app.dependencies import ( get_box_data, get_box_update_data, get_open_box_data, - get_pricing_service + get_pricing_service, + get_tcgplayer_api_service ) logger = logging.getLogger(__name__) @@ -313,3 +316,23 @@ async def update_cookies( status_code=500, detail=f"Failed to update cookies: {str(e)}" ) + +class TCGPlayerOrderRequest(BaseModel): + order_ids: List[str] + +@router.post("/processOrders", response_model=ProcessOrdersResponse) +async def process_orders( + body: TCGPlayerOrderRequest, + tcgplayer_api_service: TCGPlayerAPIService = Depends(get_tcgplayer_api_service), +) -> ProcessOrdersResponse: + """Process TCGPlayer orders.""" + try: + orders = tcgplayer_api_service.process_orders(body.order_ids) + return ProcessOrdersResponse( + status_code=200, + success=True, + orders=orders + ) + except Exception as e: + logger.error(f"Process orders failed: {str(e)}") + raise HTTPException(status_code=400, detail=str(e)) \ No newline at end of file diff --git a/app/schemas/order.py b/app/schemas/order.py deleted file mode 100644 index 77c9c57..0000000 --- a/app/schemas/order.py +++ /dev/null @@ -1,19 +0,0 @@ -from pydantic import BaseModel, Field, ConfigDict -from typing import Optional -from datetime import datetime - - -# FILE -class OrderSchema(BaseModel): - id: str = Field(..., title="id") - filename: str = Field(..., title="filename") - type: str = Field(..., title="type") - filesize_kb: float = Field(..., title="filesize_kb") - source: str = Field(..., title="source") - status: str = Field(..., title="status") - service: Optional[str] = Field(None, title="service") - date_created: datetime = Field(..., title="date_created") - date_modified: datetime = Field(..., title="date_modified") - - # This enables ORM mode - model_config = ConfigDict(from_attributes=True) \ No newline at end of file diff --git a/app/schemas/orders.py b/app/schemas/orders.py new file mode 100644 index 0000000..ee4d4bf --- /dev/null +++ b/app/schemas/orders.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel + +class OrderSchema(BaseModel): + order_id: str + +class ProcessOrdersResponse(BaseModel): + status_code: int + success: bool + orders: list[str] diff --git a/app/services/print.py b/app/services/print.py index eb0eb81..78d2665 100644 --- a/app/services/print.py +++ b/app/services/print.py @@ -10,7 +10,7 @@ import io # Printer settings printer_model = "QL-1100" -backend = 'pyusb' # Changed from network to USB +backend = 'pyusb' printer = 'usb://0x04f9:0x20a7' def convert_pdf_to_image(pdf_path): @@ -45,6 +45,8 @@ def create_address_label(input_data, font_size=30, is_pdf=False): font = ImageFont.truetype("C:\\Windows\\Fonts\\arial.ttf", size=font_size) elif platform.system() == 'Darwin': font = ImageFont.truetype("/Library/Fonts/Arial.ttf", size=font_size) + elif platform.system() == 'Linux': + font = ImageFont.truetype("/usr/share/fonts/truetype/msttcorefonts/arial.ttf", size=font_size) margin = 20 lines = input_data.split('\n') @@ -71,10 +73,8 @@ def print_address_label(input_data, font_size=30, is_pdf=False, label_size='29x9 if not image: raise Exception("Failed to create label image") - # For 4x6 shipping labels from Pirate Ship if label_size == '4x6': - # Resize image to fit 4x6 format if needed - target_width = 1164 # Adjusted for 4x6 format + target_width = 1164 target_height = 1660 image = image.resize((target_width, target_height), Image.LANCZOS) @@ -92,7 +92,6 @@ def print_address_label(input_data, font_size=30, is_pdf=False, label_size='29x9 red=False, dpi_600=False, hq=True, - #cut=True cut=False ) @@ -135,34 +134,24 @@ def process_tcg_shipping_export(file_path, require_input=False, font_size=60, pr else: sleep(1) -# Example usage if __name__ == "__main__": - # Example for regular address label - address = """John Doe -123 Main Street -Apt 4B -City, State 12345""" - - # Example for TCG Player export - shipping_export_file = "_TCGplayer_ShippingExport_20250201_115949.csv" - - # Example for Pirate Ship PDF - pirate_ship_pdf = "C:\\Users\\joshu\\Downloads\\2025-02-10---greg-creek---9400136208070411592215.pdf" - # Choose which type to process label_type = input("Enter label type (1 for regular, 2 for TCG, 3 for Pirate Ship): ") if label_type == "1": + address = input("Enter the address to print: ") preview_label(address, font_size=60) user_input = input("Press 'p' to print the label or any other key to cancel: ") if user_input.lower() == 'p': print_address_label(address, font_size=60) elif label_type == "2": + shipping_export_file = input("Enter the path to the TCG Player shipping export CSV file: ") process_tcg_shipping_export(shipping_export_file, font_size=60, preview=False) elif label_type == "3": + pirate_ship_pdf = input("Enter the path to the Pirate Ship PDF file: ") process_pirate_ship_pdf(pirate_ship_pdf, preview=True) user_input = input("Press 'p' to print the label or any other key to cancel: ") if user_input.lower() == 'p': - process_pirate_ship_pdf(pirate_ship_pdf, preview=False) + process_pirate_ship_pdf(pirate_ship_pdf, preview=False) \ No newline at end of file diff --git a/app/services/tcgplayer.py b/app/services/tcgplayer.py index b3e9feb..b2bfa8b 100644 --- a/app/services/tcgplayer.py +++ b/app/services/tcgplayer.py @@ -21,6 +21,7 @@ import pandas as pd from sqlalchemy.exc import SQLAlchemyError from app.schemas.file import CreateFileRequest import os +from app.services.util._docker import DockerUtil logger = logging.getLogger(__name__) @@ -53,6 +54,7 @@ class TCGPlayerService: self.previous_request_time = None self.df_util = DataframeUtil() self.file_service = file_service + self.docker_util = DockerUtil() def _insert_groups(self, groups): for group in groups: @@ -118,47 +120,6 @@ class TCGPlayerService: except Exception as e: logger.error(f"Failed to get browser cookies: {str(e)}") return None - - def is_in_docker(self) -> bool: - """Check if we're running inside a Docker container using multiple methods""" - # Method 1: Check cgroup - try: - with open('/proc/1/cgroup', 'r') as f: - content = f.read().lower() - if any(container_id in content for container_id in ['docker', 'containerd', 'kubepods']): - logger.debug("Docker detected via cgroup") - return True - except Exception as e: - logger.debug(f"Could not read cgroup file: {e}") - - # Method 2: Check /.dockerenv file - if os.path.exists('/.dockerenv'): - logger.debug("Docker detected via /.dockerenv file") - return True - - # Method 3: Check environment variables - docker_env = any(os.environ.get(var, False) for var in [ - 'DOCKER_CONTAINER', - 'IN_DOCKER', - 'KUBERNETES_SERVICE_HOST', # For k8s - 'DOCKER_HOST' - ]) - if docker_env: - logger.debug("Docker detected via environment variables") - return True - - # Method 4: Check container runtime - try: - with open('/proc/self/mountinfo', 'r') as f: - content = f.read().lower() - if any(rt in content for rt in ['docker', 'containerd', 'kubernetes']): - logger.debug("Docker detected via mountinfo") - return True - except Exception as e: - logger.debug(f"Could not read mountinfo: {e}") - - logger.debug("No Docker environment detected") - return False def _send_request(self, url: str, method: str, data=None, except_302=False) -> requests.Response: """Send a request with the specified cookies""" @@ -173,7 +134,7 @@ class TCGPlayerService: # Move cookie initialization outside and make it more explicit if not self.cookies: - if self.is_in_docker(): + if self.docker_util.is_in_docker(): logger.debug("Running in Docker - using cookies from file") self.cookies = self.get_cookies_from_file() else: diff --git a/app/services/tcgplayer_api.py b/app/services/tcgplayer_api.py new file mode 100644 index 0000000..f7048fa --- /dev/null +++ b/app/services/tcgplayer_api.py @@ -0,0 +1,105 @@ +from dataclasses import dataclass +import logging +from app.db.models import Orders, OrderProducts, CardTCGPlayer +from app.services.util._requests import RequestsUtil +from app.services.util._docker import DockerUtil +from app.db.utils import db_transaction +from sqlalchemy.orm import Session +from uuid import uuid4 as uuid + +logger = logging.getLogger(__name__) + +@dataclass +class TCGPlayerAPIConfig: + """Configuration for TCGPlayer API""" + ORDER_BASE_URL: str = "https://order-management-api.tcgplayer.com/orders" + API_VERSION: str = "?api-version=2.0" + +class TCGPlayerAPIService: + def __init__(self, db: Session): + self.db = db + self.docker_util = DockerUtil() + self.requests_util = RequestsUtil() + self.is_in_docker = self.docker_util.is_in_docker() + self.config = TCGPlayerAPIConfig() + self.cookies = self.get_cookies() + + def get_cookies(self) -> dict: + if self.is_in_docker: + return self.requests_util.get_tcgplayer_cookies_from_file() + else: + return self.requests_util.get_tcgplayer_browser_cookies() + + def get_order(self, order_id: str) -> dict: + url = f"{self.config.ORDER_BASE_URL}/{order_id}{self.config.API_VERSION}" + response = self.requests_util.send_request(url, method='GET', cookies=self.cookies) + if response: + return response.json() + return None + + def get_product_ids_from_sku(self, sku_ids: list[str]) -> dict: + """Get product IDs from TCGPlayer SKU IDs""" + tcg_cards = self.db.query(CardTCGPlayer).filter(CardTCGPlayer.tcgplayer_id.in_(sku_ids)).all() + return {card.tcgplayer_id: card.product_id for card in tcg_cards} + + def save_order(self, order: dict): + # check if order exists by order number + order_number = order['orderNumber'] + existing_order = self.db.query(Orders).filter(Orders.order_id == order_number).first() + if existing_order: + logger.info(f"Order {order_number} already exists in database") + return existing_order + transaction = order['transaction'] + shipping = order['shippingAddress'] + products = order['products'] + with db_transaction(self.db): + db_order = Orders( + id = str(uuid()), + order_id=order_number, + buyer_name=order['buyerName'], + recipient_name=shipping['recipientName'], + recipient_address_one=shipping['addressOne'], + recipient_address_two=shipping['addressTwo'] if 'addressTwo' in shipping else '', + recipient_city=shipping['city'], + recipient_state=shipping['territory'], + recipient_zip=shipping['postalCode'], + recipient_country=shipping['country'], + order_date=order['createdAt'], + status=order['status'], + num_products=len(products), + num_cards=sum([product['quantity'] for product in products]), + product_amount=transaction['productAmount'], + shipping_amount=transaction['shippingAmount'], + gross_amount=transaction['grossAmount'], + fee_amount=transaction['feeAmount'], + net_amount=transaction['netAmount'], + direct_fee_amount=transaction['directFeeAmount'] + ) + self.db.add(db_order) + + product_ids = [product['skuId'] for product in products] + sku_to_product_id_mapping = self.get_product_ids_from_sku(product_ids) + order_products = [] + for product in products: + product_id = sku_to_product_id_mapping.get(product['skuId']) + if product_id: + order_products.append( + OrderProducts( + id=str(uuid()), + order_id=db_order.id, + product_id=product_id, + quantity=product['quantity'], + unit_price=product['unitPrice'] + ) + ) + self.db.add_all(order_products) + return db_order + + def process_orders(self, orders: list[str]): + processed_orders = [] + for order_id in orders: + order = self.get_order(order_id) + if order: + self.save_order(order) + processed_orders.append(order_id) + return processed_orders \ No newline at end of file diff --git a/app/services/util/_docker.py b/app/services/util/_docker.py new file mode 100644 index 0000000..3b18e72 --- /dev/null +++ b/app/services/util/_docker.py @@ -0,0 +1,49 @@ +import os +import logging + +logger = logging.getLogger(__name__) + +class DockerUtil: + def __init__(self): + pass + + def is_in_docker(self) -> bool: + """Check if we're running inside a Docker container using multiple methods""" + # Method 1: Check cgroup + try: + with open('/proc/1/cgroup', 'r') as f: + content = f.read().lower() + if any(container_id in content for container_id in ['docker', 'containerd', 'kubepods']): + logger.debug("Docker detected via cgroup") + return True + except Exception as e: + logger.debug(f"Could not read cgroup file: {e}") + + # Method 2: Check /.dockerenv file + if os.path.exists('/.dockerenv'): + logger.debug("Docker detected via /.dockerenv file") + return True + + # Method 3: Check environment variables + docker_env = any(os.environ.get(var, False) for var in [ + 'DOCKER_CONTAINER', + 'IN_DOCKER', + 'KUBERNETES_SERVICE_HOST', # For k8s + 'DOCKER_HOST' + ]) + if docker_env: + logger.debug("Docker detected via environment variables") + return True + + # Method 4: Check container runtime + try: + with open('/proc/self/mountinfo', 'r') as f: + content = f.read().lower() + if any(rt in content for rt in ['docker', 'containerd', 'kubernetes']): + logger.debug("Docker detected via mountinfo") + return True + except Exception as e: + logger.debug(f"Could not read mountinfo: {e}") + + logger.debug("No Docker environment detected") + return False \ No newline at end of file diff --git a/app/services/util/_requests.py b/app/services/util/_requests.py new file mode 100644 index 0000000..3c33734 --- /dev/null +++ b/app/services/util/_requests.py @@ -0,0 +1,172 @@ +from typing import Dict, Optional +from app.services.util._docker import DockerUtil +from enum import Enum +import browser_cookie3 +import os +import json +import requests +import time +from datetime import datetime +import logging + +logger = logging.getLogger(__name__) + +class Browser(Enum): + """Supported browser types for cookie extraction""" + BRAVE = "brave" + CHROME = "chrome" + FIREFOX = "firefox" + +class Method(Enum): + """Supported HTTP methods""" + GET = "GET" + POST = "POST" + +class TCGPlayerEndpoints(Enum): + """Supported TCGPlayer API endpoints""" + ORDERS = "https://order-management-api.tcgplayer.com/orders" + +class Headers: + ACCEPT = 'application/json, text/plain, */*' + ACCEPT_ENCODING = 'gzip, deflate, br, zstd' + ACCEPT_LANGUAGE = 'en-US,en;q=0.8' + PRIORITY = 'u=1, i' + SECCHUA = '"Not(A:Brand";v="99", "Brave";v="133", "Chromium";v="133"' + SECCHUA_MOBILE = '?0' + SECCHUA_PLATFORM = '"macOS"' + SEC_FETCH_DEST = 'empty' + SEC_FETCH_MODE = 'cors' + SEC_FETCH_SITE = 'same-site' + SEC_GPC = '1' + USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36' + SELLER_ORIGIN = 'https://sellerportal.tcgplayer.com' + SELLER_REFERER = 'https://sellerportal.tcgplayer.com/' + +class RequestHeaders: + BASE_HEADERS = { + 'accept': Headers.ACCEPT, + 'accept-encoding': Headers.ACCEPT_ENCODING, + 'accept-language': Headers.ACCEPT_LANGUAGE, + 'priority': Headers.PRIORITY, + 'sec-ch-ua': Headers.SECCHUA, + 'sec-ch-ua-mobile': Headers.SECCHUA_MOBILE, + 'sec-ch-ua-platform': Headers.SECCHUA_PLATFORM, + 'sec-fetch-dest': Headers.SEC_FETCH_DEST, + 'sec-fetch-mode': Headers.SEC_FETCH_MODE, + 'sec-fetch-site': Headers.SEC_FETCH_SITE, + 'sec-gpc': Headers.SEC_GPC, + 'user-agent': Headers.USER_AGENT + } + SELLER_HEADERS = { + 'origin': Headers.SELLER_ORIGIN, + 'referer': Headers.SELLER_REFERER + } + +class URLHeaders: + # combine base and seller headers + ORDER_HEADERS = {**RequestHeaders.BASE_HEADERS, **RequestHeaders.SELLER_HEADERS} + +class RequestsUtil: + def __init__(self, browser_type: Browser = Browser.BRAVE): + self.browser_type = browser_type + self.docker_util = DockerUtil() + + def get_tcgplayer_cookies_from_file(self) -> Dict: + # check if cookies file exists + if not os.path.exists('cookies/tcg_cookies.json'): + raise ValueError("Cookies file not found") + with open('cookies/tcg_cookies.json', 'r') as f: + logger.debug("Loading cookies from file") + cookies = json.load(f) + return cookies + + def get_tcgplayer_browser_cookies(self) -> Optional[Dict]: + """Retrieve cookies from the specified browser""" + try: + cookie_getter = getattr(browser_cookie3, self.browser_type.value, None) + if not cookie_getter: + raise ValueError(f"Unsupported browser type: {self.browser_type.value}") + return cookie_getter() + except Exception as e: + logger.error(f"Failed to get browser cookies: {str(e)}") + return None + + def rate_limit(self, time_between_requests: int = 10): + """Rate limit requests by waiting for a specified time between requests""" + time_diff = (datetime.now() - self.previous_request_time).total_seconds() + if time_diff < time_between_requests: + # logger.info(f"Waiting {time_between_requests - time_diff} seconds before next request...") + time.sleep(time_between_requests - time_diff) + + def send_request(self, url: str, method: str, cookies: dict, data=None) -> requests.Response: + """Send a request with the specified cookies""" + + headers = self.set_headers(url) + if not headers: + raise ValueError("Headers not set") + + try: + response = requests.request(method, url, headers=headers, cookies=cookies, data=data) + response.raise_for_status() + self.previous_request_time = datetime.now() + + return response + + except requests.RequestException as e: + logger.error(f"Request failed: {str(e)}") + return None + + def set_headers(self, url: str): + # use tcgplayerendpoints enum to set headers where url partially matches enum value + for endpoint in TCGPlayerEndpoints: + if endpoint.value in url: + return URLHeaders.ORDER_HEADERS + else: + raise ValueError(f"Endpoint not found in TCGPlayerEndpoints: {url}") + + def old_set_headers(self, method: str) -> Dict: + base_headers = { + 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8', + 'accept-language': 'en-US,en;q=0.8', + 'priority': 'u=0, i', + 'referer': 'https://store.tcgplayer.com/admin/pricing', + 'sec-ch-ua': '"Not A(Brand";v="8", "Chromium";v="132", "Brave";v="132"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'sec-fetch-dest': 'document', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-site': 'same-origin', + 'sec-fetch-user': '?1', + 'sec-gpc': '1', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36' + } + + if method == 'POST': + post_headers = { + 'cache-control': 'max-age=0', + 'content-type': 'application/x-www-form-urlencoded', + 'origin': 'https://store.tcgplayer.com' + } + base_headers.update(post_headers) + + return base_headers + + +""" +curl 'https://order-management-api.tcgplayer.com/orders/E576ED4C-38871F-B0277?api-version=2.0' \ + -H 'accept: application/json, text/plain, */*' \ + -H 'accept-language: en-US,en;q=0.8' \ + -b 'tcgpartner=PK=TRADECARDS&M=1; valid=set=true; product-display-settings=sort=price+shipping&size=10; TCG_Data=M=1&SearchGameNameID=magic; tcg-uuid=ab16b5f8-dd66-446d-b217-d394328a5cf1; setting=CD=US&M=1; 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}}; OAuthLoginSessionId=63b1a89d-1ac2-43f7-8e79-55a9ca5e761d; TCGAuthTicket_Production=F453BFF2FA3FAA3D1ACA23F319314F8273713DECEB06C69BB7C208A77C81559B46E1AA22A7E70FABC8D7F681A423C86870FAE318B76048CDE7BF6D73D220631B899BEBA86C422E1EBBF2ACD1921E0846F708AFE203C844031364E13B047465E7B41CB6460E4F4AAB278B614445B93E722E976688; BuyerRevalidationKey=; ASP.NET_SessionId=oouwzrh3jkhdrmaioooqhr4k; TCG_VisitorKey=431efcca-2d5b-404d-a04f-3ae979696051; __RequestVerificationToken_L2FkbWlu0=Lw1sfWh823UeJ7zRux0b1ZTI4Vg4i_dFt97a55aQpf-qBURVuwWDCJyuCxSwgLNLe9nPlfDSc1AMV5nyqhY4Q4jurxs1; fileDownloadToken=1740145585435; spDisabledUIFeatures=' \ + -H 'origin: https://sellerportal.tcgplayer.com' \ + -H 'priority: u=1, i' \ + -H 'referer: https://sellerportal.tcgplayer.com/' \ + -H 'sec-ch-ua: "Not(A:Brand";v="99", "Brave";v="133", "Chromium";v="133"' \ + -H 'sec-ch-ua-mobile: ?0' \ + -H 'sec-ch-ua-platform: "macOS"' \ + -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 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36' +""" \ No newline at end of file diff --git a/requests.md b/requests.md index c5b9615..8fce19d 100644 --- a/requests.md +++ b/requests.md @@ -2,16 +2,20 @@ curl -J http://192.168.1.41:8000/api/tcgplayer/inventory/update --remote-name curl -J -X POST http://192.168.1.41:8000/api/tcgplayer/inventory/add \ -H "Content-Type: application/json" \ - -d '{"open_box_ids": ["fb629d9d-13d2-405e-9a69-6c44294d55de"]}' \ + -d '{"open_box_ids": ["02d14109-ad0c-41f9-b49f-24134f962c1a"]}' \ --remote-name curl -X POST http://192.168.1.41:8000/api/boxes \ --F "type=draft" \ --F "set_code=CLB" \ --F "sku=195166181127" \ --F "num_cards_expected=480" +-F "type=play" \ +-F "set_code=DFT" \ +-F "sku=195166278636" \ +-F "num_cards_expected=422" -curl -X POST "http://192.168.1.41:8000/api/boxes/0d31b9c3-3093-438a-9e8c-b6b70a2d437e/open" \ - -F "product_id=0d31b9c3-3093-438a-9e8c-b6b70a2d437e" \ - -F "file_ids=bb4a022c-5427-49b5-b57c-0147b5e9c4a9" \ - -F "date_opened=2025-02-15" \ No newline at end of file +curl -X POST "http://192.168.1.41:8000/api/boxes/0d605f46-25b5-4784-8d45-38dec144ec8e/open" \ + -F "product_id=0d605f46-25b5-4784-8d45-38dec144ec8e" \ + -F "file_ids=61124a9d-8db3-49aa-bf56-ec0d784ca817" \ + -F "date_opened=2025-02-17" + +curl -X POST "http://127.0.0.1:8000/api/processOrders" \ + -H "Content-Type: application/json" \ + -d '{"order_ids": ["E576ED4C-A1117E-6904E"]}' \ No newline at end of file