api.py

3.4 kB · python · 105 lines

1import json2from mrlypy.core.helpers import create_logger3from . import http4from .config import (5    PRINTFUL_API_KEY,6    PRINTFUL_URL,7    SHOPIFY_ADMIN_URL,8    SHOPIFY_AUTH_URL,9    SHOPIFY_CLIENT_ID,10    SHOPIFY_SECRET,11)12from .errors import PrintfulError, Retry, ShopifyError, TaskAborted13from .models import Task1415BODY_LIMIT = 3001617logger = create_logger("carlomitchener-automator")1819TOKEN = {"admin": None}2021def extract_gid(gid: str) -> str:22    return gid.split("/")[-1]2324def clip(text: str) -> str:25    return text[:BODY_LIMIT].replace("\n", " ")2627def log(task: Task, method: str, url: str, status: int) -> None:28    logger.info(f"{task.desc} {task.step} {method} {url} {status}")2930# TOKEN3132def mint_token() -> None:33    payload = {34        "client_id": SHOPIFY_CLIENT_ID,35        "client_secret": SHOPIFY_SECRET,36        "grant_type": "client_credentials",37    }38    response = http.request("POST", SHOPIFY_AUTH_URL, data=payload)39    if response.status_code != 200:40        raise ShopifyError(f"admin token {response.status_code}")41    result = response.json()42    if "access_token" not in result:43        raise ShopifyError("admin token refused")44    TOKEN["admin"] = result["access_token"]45    logger.info(f"admin token minted for {SHOPIFY_ADMIN_URL}")4647# PRINTFUL4849def printful_request(task: Task, method: str, path: str, data: dict = None, allow_404: bool = False) -> dict:50    url = f"{PRINTFUL_URL}{path}"51    headers = {"Authorization": f"Bearer {PRINTFUL_API_KEY}"}52    response = http.request(method, url, headers=headers, json_data=data)53    log(task, method, url, response.status_code)54    if response.status_code == 429:55        raise Retry("printful 429")56    if response.status_code == 400:57        raise TaskAborted(f"printful 400 {clip(response.text)}")58    if response.status_code == 404:59        if allow_404:60            return {}61        raise TaskAborted(f"printful 404 {clip(response.text)}")62    if response.status_code != 200:63        raise PrintfulError(f"printful {response.status_code} {clip(response.text)}")64    return response.json()6566# SHOPIFY6768def shopify_request(task: Task, query: str, variables: dict = None) -> dict:69    headers = {"X-Shopify-Access-Token": TOKEN["admin"]}70    payload = {"query": query, "variables": variables}71    response = http.request("POST", SHOPIFY_ADMIN_URL, headers=headers, json_data=payload)72    log(task, "POST", SHOPIFY_ADMIN_URL, response.status_code)73    if response.status_code == 429:74        raise Retry("shopify 429")75    if response.status_code != 200:76        raise ShopifyError(f"shopify {response.status_code}")77    result = response.json()78    if "errors" in result:79        raise ShopifyError(f"shopify errors {clip(json.dumps(result['errors']))}")80    return result8182def check_errors(result: dict, name: str) -> dict:83    data = result["data"][name]84    errors = data["userErrors"]85    if errors:86        raise TaskAborted(f"{name} userErrors {clip(json.dumps(errors))}")87    return data8889DELETE_PRODUCT = """90mutation productDelete($input: ProductDeleteInput!) {91    productDelete(input: $input) {92        deletedProductId93        userErrors {94            field95            message96        }97    }98}99"""100101def delete_product(task: Task) -> None:102    variables = {"input": {"id": task.product.shopify_id}}103    result = shopify_request(task, DELETE_PRODUCT, variables)104    check_errors(result, "productDelete")105    logger.info(f"{task.desc} deleted shopify product {task.product.shopify_id}")