90 lines
3.3 KiB
Python
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()
|