Files
Sipro-Stocks/marketplaces/wildberries.py

90 lines
3.3 KiB
Python

import asyncio
import json
import logging
from typing import Union
import jwt
import utils
from database import Marketplace
from limiter import BatchLimiter
from marketplaces.base import BaseMarketplaceApi
class WildberriesMarketplaceApi(BaseMarketplaceApi):
def __init__(self, marketplace: Marketplace):
self.marketplace = marketplace
auth_data = json.loads(marketplace.auth_data)
token = auth_data.get('token')
self.is_valid = True
try:
decoded_token = jwt.decode(token, algorithms=["HS256"], options={"verify_signature": False})
except Exception:
logging.error(f"Couldn't decode token for {marketplace.id}")
self.is_valid = False
return
self.limiter_key = str(marketplace.company_id) + str(decoded_token.get('sid'))
self.headers = {
'Authorization': token,
'Content-Type': 'application/json',
'User-Agent': 'wbas_seller.denco.store3547'
}
def get_headers(self):
return self.headers
@property
def api_url(self):
return 'https://marketplace-api.wildberries.ru'
async def update_stocks(self, data: Union[list, dict]):
if type(data) is not list:
return
if not self.is_valid:
logging.warning(f'Skipping marketplace [{self.marketplace.id}] because of invalid token')
return
max_stocks = 1000
chunks = list(utils.chunk_list(data, max_stocks))
if not chunks:
return
self.init_session()
limiter = BatchLimiter()
chunk = chunks.pop()
while True:
try:
if not chunks:
break
await limiter.acquire_wildberries(self.limiter_key)
request_data = {'stocks': chunk}
response = await self._method('PUT', f'/api/v3/stocks/{self.marketplace.warehouse_id}',
data=request_data)
if (response.status not in [204, 409]) and (response.status != 429):
response = await response.json()
error_message = response.get('message')
error_code = response.get('code')
logging.warning(
f'Error occurred when sending stocks to [{self.marketplace.id}]: {error_message} ({error_code})')
break
if response.status == 429:
await asyncio.sleep(1)
logging.warning(f'Rate limit exceeded for marketplace [{self.marketplace.id}]')
continue
chunk = chunks.pop()
await asyncio.sleep(0.2)
except Exception as e:
logging.error(
f'Exception occurred while sending stocks to marketplace ID [{self.marketplace.id}]: {str(e)}')
# tasks = [send_stock_chunk(chunk) for chunk in chunks]
# first_request = tasks[0]
# first_response = await first_request
# if not first_response:
# logging.error(f'Skipping marketplace [{self.marketplace.id}] because first request was unsuccessful')
# await self.session.close()
# return
#
# await asyncio.gather(*tasks[1:])
await self.session.close()