initial commit
This commit is contained in:
commit
8befcd2896
9 changed files with 324 additions and 0 deletions
7
Pipfile
Normal file
7
Pipfile
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
[[source]]
|
||||||
|
url = "https://pypi.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
name = "pypi"
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
api-client-pydantic = "*"
|
||||||
0
README.md
Normal file
0
README.md
Normal file
4
pyrohlik/__init__.py
Normal file
4
pyrohlik/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .client import Rohlik
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ('Rohlik', )
|
||||||
36
pyrohlik/client.py
Normal file
36
pyrohlik/client.py
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
from apiclient import APIClient, endpoint, JsonResponseHandler, HeaderAuthentication
|
||||||
|
from apiclient_pydantic import serialize
|
||||||
|
|
||||||
|
from .models.order import Order, Orders
|
||||||
|
from .models.product import Product
|
||||||
|
from .models.recipe import Recipe
|
||||||
|
from .endpoints import Endpoints
|
||||||
|
|
||||||
|
|
||||||
|
class Rohlik(APIClient):
|
||||||
|
def __init__(self, api_key: str):
|
||||||
|
super().__init__(response_handler=JsonResponseHandler, authentication_method=HeaderAuthentication(token=api_key,parameter="x-api-authorization",scheme="token"))
|
||||||
|
# self.response_handler=JsonResponseHandler
|
||||||
|
# self.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))
|
||||||
|
product['prices'] = prices
|
||||||
|
product['stock'] = stock
|
||||||
|
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']
|
||||||
10
pyrohlik/endpoints.py
Normal file
10
pyrohlik/endpoints.py
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
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'
|
||||||
79
pyrohlik/models/order.py
Normal file
79
pyrohlik/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
|
||||||
|
|
||||||
|
|
||||||
|
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(BaseModel):
|
||||||
|
__root__: List[OrderList]
|
||||||
84
pyrohlik/models/product.py
Normal file
84
pyrohlik/models/product.py
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
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: 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 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[str] = Field(..., alias='shelfLife')
|
||||||
|
billable_packaging: Optional[str] = Field(..., alias='billablePackaging')
|
||||||
|
sales: List[SaleStock]
|
||||||
|
in_stock: bool = Field(..., alias='inStock')
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
103
pyrohlik/models/recipe.py
Normal file
103
pyrohlik/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
|
||||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
api-client-pydantic
|
||||||
Loading…
Add table
Add a link
Reference in a new issue