rename module pyrohlik to rohlik
This commit is contained in:
parent
d10cef9705
commit
e3ba823070
8 changed files with 1 additions and 1 deletions
4
rohlik/__init__.py
Normal file
4
rohlik/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
from .client import Rohlik
|
||||
|
||||
|
||||
__all__ = ('Rohlik', )
|
||||
72
rohlik/client.py
Normal file
72
rohlik/client.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import uuid
|
||||
from apiclient import APIClient, endpoint, JsonRequestFormatter, JsonResponseHandler, HeaderAuthentication
|
||||
from apiclient_pydantic import serialize
|
||||
|
||||
from .models.order import Order, Orders
|
||||
from .models.product import Product
|
||||
from .models.recipe import Recipe
|
||||
from .models.cart import Cart, AddItem, Add
|
||||
from .endpoints import Endpoints
|
||||
|
||||
|
||||
class Rohlik(APIClient):
|
||||
def __init__(self, api_key: str):
|
||||
super().__init__(request_formatter=JsonRequestFormatter, response_handler=JsonResponseHandler, authentication_method=HeaderAuthentication(token=api_key,parameter="x-api-authorization",scheme="token"))
|
||||
|
||||
@serialize()
|
||||
def get_product(self, product_id: int) -> Product:
|
||||
product = self.get(Endpoints.product.format(product_id=product_id))
|
||||
prices = self.get(Endpoints.prices.format(product_id=product_id))
|
||||
stock = self.get(Endpoints.stock.format(product_id=product_id))
|
||||
description = self.get(Endpoints.description.format(product_id=product_id))
|
||||
composition = self.get(Endpoints.composition.format(product_id=product_id))
|
||||
product['prices'] = prices
|
||||
product['stock'] = stock
|
||||
product['description'] = description['description']
|
||||
product['composition'] = composition
|
||||
return product
|
||||
|
||||
@serialize()
|
||||
def get_order(self, order_id: int) -> Order:
|
||||
return self.get(Endpoints.order.format(order_id=order_id))
|
||||
|
||||
@serialize()
|
||||
def get_orders(self) -> Orders:
|
||||
return self.get(Endpoints.orders_delivered)
|
||||
|
||||
@serialize()
|
||||
def get_recipe(self, recipe_id: int) -> Recipe:
|
||||
recipe_response = self.get(Endpoints.recipe.format(recipe_id=recipe_id))
|
||||
return recipe_response['data']
|
||||
|
||||
@serialize()
|
||||
def get_cart(self) -> Cart:
|
||||
return self.get(Endpoints.cart)
|
||||
|
||||
@serialize()
|
||||
def add_to_cart(self, product_id) -> Cart:
|
||||
add = Add()
|
||||
add_item=AddItem()
|
||||
add_item.uuid=str(uuid.uuid4())
|
||||
add_item.product_id = product_id
|
||||
add_item.action_type = "modify"
|
||||
add_item.amount = 1
|
||||
add_item.source = "hp-v2"
|
||||
add_item.sale_id = 0
|
||||
add.items = []
|
||||
add.items.append(add_item)
|
||||
return self.patch(Endpoints.cart, add.dict(by_alias=True))
|
||||
|
||||
@serialize()
|
||||
def remove_from_cart(self, product_id) -> Cart:
|
||||
add = Add()
|
||||
add_item=AddItem()
|
||||
add_item.uuid=str(uuid.uuid4())
|
||||
add_item.product_id = product_id
|
||||
add_item.action_type = "modify"
|
||||
add_item.amount = -1
|
||||
add_item.source = "hp-v2"
|
||||
add_item.sale_id = 0
|
||||
add.items = []
|
||||
add.items.append(add_item)
|
||||
return self.patch(Endpoints.cart, add.dict(by_alias=True))
|
||||
13
rohlik/endpoints.py
Normal file
13
rohlik/endpoints.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
from apiclient import endpoint
|
||||
|
||||
@endpoint(base_url='https://www.rohlik.cz')
|
||||
class Endpoints:
|
||||
product: str = 'api/v1/products/{product_id}'
|
||||
order: str = 'api/v3/orders/{order_id}'
|
||||
orders_delivered: str = 'api/v3/orders/delivered'
|
||||
recipe: str = 'services/frontend-service/recipe/{recipe_id}'
|
||||
prices: str = 'api/v1/products/{product_id}/prices'
|
||||
stock: str = 'api/v1/products/{product_id}/stock'
|
||||
description: str = 'api/v1/products/{product_id}/description'
|
||||
composition: str = 'api/v1/products/{product_id}/composition'
|
||||
cart: str = 'api/v2/cart'
|
||||
73
rohlik/models/cart.py
Normal file
73
rohlik/models/cart.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
from typing import Any, List, Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class Store(BaseModel):
|
||||
store_id: int = Field(..., alias='storeId')
|
||||
zone_id: int = Field(..., alias='zoneId')
|
||||
type: str
|
||||
|
||||
|
||||
class FlatDetails(BaseModel):
|
||||
entrance: Optional[str]
|
||||
floor: Optional[str]
|
||||
door: Optional[str]
|
||||
block: Optional[str]
|
||||
apartment: Optional[str]
|
||||
staircase: Optional[str]
|
||||
intercom: Optional[str]
|
||||
additional_info: Optional[str] = Field(..., alias='additionalInfo')
|
||||
|
||||
|
||||
class Address(BaseModel):
|
||||
id: int
|
||||
city: str
|
||||
street: str
|
||||
house_number: str = Field(..., alias='houseNumber')
|
||||
orientation_number: str = Field(..., alias='orientationNumber')
|
||||
latitude: float
|
||||
longitude: float
|
||||
postal_code: str = Field(..., alias='postalCode')
|
||||
display: str
|
||||
stores: List[Store]
|
||||
flat_details: FlatDetails = Field(..., alias='flatDetails')
|
||||
additional_address_details: List[str] = Field(..., alias='additionalAddressDetails')
|
||||
|
||||
|
||||
class Destination(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
type: str
|
||||
access_type: str = Field(..., alias='accessType')
|
||||
location_type: str = Field(..., alias='locationType')
|
||||
delivery_point_provider: Optional[str] = Field(..., alias='deliveryPointProvider')
|
||||
photos: Optional[str]
|
||||
address: Address
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
product_id: int = Field(..., alias='productId')
|
||||
amount: int
|
||||
sale_id: int = Field(..., alias='saleId')
|
||||
result: str
|
||||
|
||||
|
||||
class Cart(BaseModel):
|
||||
status: str
|
||||
cart_id: int = Field(..., alias='cartId')
|
||||
store: Store
|
||||
destination: Destination
|
||||
items: List[Item]
|
||||
|
||||
|
||||
class AddItem(BaseModel):
|
||||
source: Optional[str]
|
||||
product_id: Optional[int] = Field(alias='productId')
|
||||
sale_id: Optional[int] = Field(alias='saleId')
|
||||
action_type: Optional[str] = Field(alias='actionType')
|
||||
amount: Optional[int]
|
||||
uuid: Optional[str]
|
||||
|
||||
|
||||
class Add(BaseModel):
|
||||
items: Optional[List[AddItem]]
|
||||
79
rohlik/models/order.py
Normal file
79
rohlik/models/order.py
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
from decimal import Decimal
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
from pydantic import BaseModel, Field, RootModel
|
||||
|
||||
|
||||
class Price(BaseModel):
|
||||
amount: Decimal
|
||||
currency: str
|
||||
|
||||
|
||||
class PriceCompositionOrder(BaseModel):
|
||||
total: Price
|
||||
goods: Price
|
||||
delivery: Price
|
||||
credits_used: Price = Field(alias='creditsUsed')
|
||||
courier_tip: Price = Field(alias='courierTip')
|
||||
fines: Price
|
||||
reusable_bags_deposit: Price = Field(alias='reusableBagsDeposit')
|
||||
|
||||
|
||||
class PriceCompositionOrderProduct(BaseModel):
|
||||
total: Price
|
||||
unit: Price
|
||||
|
||||
class PriceCompositionOrderList(BaseModel):
|
||||
total: Price
|
||||
|
||||
|
||||
class OrderProduct(BaseModel):
|
||||
name: str
|
||||
unit: str
|
||||
textual_amount: str = Field(..., alias='textualAmount')
|
||||
amount: int
|
||||
images: List[str]
|
||||
price_composition: PriceCompositionOrderProduct = Field(..., alias='priceComposition')
|
||||
compensated: bool
|
||||
id: int
|
||||
|
||||
|
||||
class DeliverySlot(BaseModel):
|
||||
id: int
|
||||
type: str
|
||||
since: datetime
|
||||
till: datetime
|
||||
|
||||
|
||||
class OrderList(BaseModel):
|
||||
id: int
|
||||
items_count: int = Field(alias='itemsCount')
|
||||
order_time: datetime = Field(alias='orderTime')
|
||||
price_composition: PriceCompositionOrderList = Field(..., alias='priceComposition')
|
||||
delivery_slot: Optional[DeliverySlot] = Field(..., alias='deliverySlot')
|
||||
|
||||
|
||||
class Document(BaseModel):
|
||||
type: str
|
||||
title: str
|
||||
link: str
|
||||
|
||||
|
||||
class Order(BaseModel):
|
||||
id: int
|
||||
items_count: int = Field(..., alias='itemsCount')
|
||||
price_composition: PriceCompositionOrder = Field(..., alias='priceComposition')
|
||||
order_time: datetime = Field(..., alias='orderTime')
|
||||
delivery_type: str = Field(..., alias='deliveryType')
|
||||
delivery_slot: DeliverySlot = Field(..., alias='deliverySlot')
|
||||
state: str
|
||||
payment: int
|
||||
address: str
|
||||
delivery_note: str = Field(..., alias='deliveryNote')
|
||||
documents: List[Document]
|
||||
available_actions: List[str] = Field(..., alias='availableActions')
|
||||
items: List[OrderProduct]
|
||||
|
||||
|
||||
class Orders(RootModel):
|
||||
root: List[OrderList]
|
||||
135
rohlik/models/product.py
Normal file
135
rohlik/models/product.py
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
from decimal import Decimal
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class Price(BaseModel):
|
||||
amount: Decimal
|
||||
currency: str
|
||||
|
||||
|
||||
class Badge(BaseModel):
|
||||
type: str
|
||||
title: str
|
||||
subtitle: Optional[str]
|
||||
tooltip: Optional[str]
|
||||
|
||||
|
||||
class Country(BaseModel):
|
||||
name: str
|
||||
name_id: str = Field(..., alias='nameId')
|
||||
code: str
|
||||
|
||||
|
||||
class SalePrice(BaseModel):
|
||||
id: int
|
||||
type: str
|
||||
trigger_amount: int = Field(..., alias='triggerAmount')
|
||||
price: Price
|
||||
price_per_unit: Price = Field(..., alias='pricePerUnit')
|
||||
badges: List[Badge]
|
||||
valid_till: str = Field(..., alias='validTill')
|
||||
active: bool
|
||||
|
||||
class ProductPrice(BaseModel):
|
||||
price: Price
|
||||
price_per_unit: Price = Field(..., alias='pricePerUnit')
|
||||
sales: List[SalePrice]
|
||||
|
||||
|
||||
class SaleStock(BaseModel):
|
||||
id: int
|
||||
amount: int
|
||||
unlimited_amount: bool = Field(..., alias='unlimitedAmount')
|
||||
shelf_life: Optional[str] = Field(..., alias='shelfLife')
|
||||
|
||||
|
||||
class ShelfLife(BaseModel):
|
||||
average: int
|
||||
minimal: int
|
||||
type: str
|
||||
bestBefore: Optional[str]
|
||||
|
||||
|
||||
class Stock(BaseModel):
|
||||
warehouse_id: int = Field(..., alias='warehouseId')
|
||||
unavailability_reason: Optional[str] = Field(..., alias='unavailabilityReason')
|
||||
preorder_enabled: bool = Field(..., alias='preorderEnabled')
|
||||
max_basket_amount: int = Field(..., alias='maxBasketAmount')
|
||||
max_basket_amount_reason: str = Field(..., alias='maxBasketAmountReason')
|
||||
delivery_restriction: Optional[str] = Field(..., alias='deliveryRestriction')
|
||||
expected_replenishment: Optional[datetime] = Field(..., alias='expectedReplenishment')
|
||||
availability_dimension: int = Field(..., alias='availabilityDimension')
|
||||
shelf_life: Optional[ShelfLife] = Field(..., alias='shelfLife')
|
||||
billable_packaging: Optional[str] = Field(..., alias='billablePackaging')
|
||||
sales: List[SaleStock]
|
||||
in_stock: bool = Field(..., alias='inStock')
|
||||
|
||||
|
||||
class Ingredient(BaseModel):
|
||||
type: str
|
||||
ingredients: List['Ingredient']
|
||||
title: str
|
||||
code: Optional[str] = None
|
||||
link: Optional[str] = None
|
||||
|
||||
|
||||
class Allergens(BaseModel):
|
||||
contained: List[str]
|
||||
possibly_contained: List[str] = Field(..., alias='possiblyContained')
|
||||
|
||||
|
||||
class AmountUnit(BaseModel):
|
||||
amount: Optional[Decimal]
|
||||
unit: str
|
||||
|
||||
|
||||
class NutritionaValues(BaseModel):
|
||||
energy_kj: AmountUnit = Field(..., alias='energyKJ')
|
||||
energy_k_cal: AmountUnit = Field(..., alias='energyKCal')
|
||||
fats: AmountUnit
|
||||
saturated_fats: AmountUnit = Field(..., alias='saturatedFats')
|
||||
carbohydrates: AmountUnit
|
||||
sugars: AmountUnit
|
||||
protein: AmountUnit
|
||||
salt: AmountUnit
|
||||
fiber: AmountUnit
|
||||
|
||||
|
||||
class NutritionalValue(BaseModel):
|
||||
portion: str
|
||||
values: NutritionaValues
|
||||
|
||||
|
||||
class Composition(BaseModel):
|
||||
nutritional_values: List[NutritionalValue] = Field(..., alias='nutritionalValues')
|
||||
ingredients: List[Ingredient]
|
||||
plain_ingredients: Optional[str] = Field(..., alias='plainIngredients')
|
||||
allergens: Optional[Allergens]
|
||||
|
||||
|
||||
class Product(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
slug: str
|
||||
main_category_id: int = Field(..., alias='mainCategoryId')
|
||||
unit: str
|
||||
textual_amount: str = Field(..., alias='textualAmount')
|
||||
badges: List[Badge]
|
||||
archived: bool
|
||||
premium_only: bool = Field(..., alias='premiumOnly')
|
||||
brand: Optional[str]
|
||||
images: List[str]
|
||||
countries: List[Country]
|
||||
can_be_favorite: bool = Field(..., alias='canBeFavorite')
|
||||
information: List
|
||||
weighted_item: bool = Field(..., alias='weightedItem')
|
||||
package_ratio: int = Field(..., alias='packageRatio')
|
||||
seller_id: int = Field(..., alias='sellerId')
|
||||
flag: Optional[str]
|
||||
attachments: List
|
||||
prices: ProductPrice
|
||||
stock: Stock
|
||||
description: str
|
||||
composition: Composition
|
||||
103
rohlik/models/recipe.py
Normal file
103
rohlik/models/recipe.py
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
from typing import List, Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class Srcset(BaseModel):
|
||||
small: str
|
||||
big: str
|
||||
|
||||
|
||||
class Image(BaseModel):
|
||||
path: str
|
||||
alt: str
|
||||
srcset: Srcset
|
||||
|
||||
|
||||
class Serving(BaseModel):
|
||||
name: str
|
||||
default: bool
|
||||
|
||||
|
||||
class Author(BaseModel):
|
||||
name: str
|
||||
annotation: str
|
||||
image_path: str = Field(..., alias='imagePath')
|
||||
|
||||
class Tip(BaseModel):
|
||||
content: str
|
||||
images: List[str]
|
||||
|
||||
|
||||
class Step(BaseModel):
|
||||
step_number: int = Field(..., alias='stepNumber')
|
||||
name: str
|
||||
content: str
|
||||
images: List[str]
|
||||
|
||||
|
||||
class Direction(BaseModel):
|
||||
name: str
|
||||
position: int
|
||||
steps: List[Step]
|
||||
|
||||
|
||||
class Tag(BaseModel):
|
||||
slug: str
|
||||
label: str
|
||||
|
||||
|
||||
class Breadcrumb(BaseModel):
|
||||
title: str
|
||||
link: str
|
||||
children: List[str]
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
ingredient_id: int = Field(..., alias='ingredientId')
|
||||
position: int
|
||||
products_count: int = Field(..., alias='productsCount')
|
||||
img_path: str = Field(..., alias='imgPath')
|
||||
ingredient_name: str = Field(..., alias='ingredientName')
|
||||
|
||||
|
||||
class Ingredient(BaseModel):
|
||||
name: str
|
||||
position: int
|
||||
items: List[Item]
|
||||
|
||||
|
||||
class IngredientsSummaryItem(BaseModel):
|
||||
name: str
|
||||
position: int
|
||||
items: List[str]
|
||||
|
||||
|
||||
class Recipe(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
annotation: str
|
||||
servings: List[Serving]
|
||||
image: Image
|
||||
author: Author
|
||||
tips: List[Tip]
|
||||
directions: List[Direction]
|
||||
ingredients: List[Ingredient]
|
||||
breadcrumbs: List[Breadcrumb]
|
||||
ingredients_summary: List[IngredientsSummaryItem] = Field(
|
||||
..., alias='ingredientsSummary'
|
||||
)
|
||||
tags: List[Tag]
|
||||
type: str
|
||||
has_all_ingredients_available: bool = Field(..., alias='hasAllIngredientsAvailable')
|
||||
link: str
|
||||
favorite: bool
|
||||
is_favorite: bool = Field(..., alias='isFavorite')
|
||||
is_new: bool = Field(..., alias='isNew')
|
||||
is_best_seller: bool = Field(..., alias='isBestSeller')
|
||||
|
||||
|
||||
class RecipeResponse(BaseModel):
|
||||
status: int
|
||||
messages: List
|
||||
recipe: Recipe
|
||||
Loading…
Add table
Add a link
Reference in a new issue