I have been working on where I create a payload of dicts with different values as store, name etc etc which you will see very soon. The idea is that with the payload I send to this script, it should see if the values is in the payload (dict) and if it is then add it into discord embed. As simple as it sounds.
I have done something like this:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import time
from threading import Thread
from typing import Dict
import pendulum
from discord_webhook import DiscordEmbed, DiscordWebhook
from loguru import logger
mixed_filtered = {
'test1': 'https://discordapp.com/api/webhooks/529345345345345/6h4_yshmNDKktdT-0VevOhqdXG9rDhRWclIfDD4jY8IbdCQ5-kllob-k1251252151',
'test2': 'https://discordapp.com/api/webhooks/529674575474577/6h4_yshmNDKktdT-0VevOhqdXG9rDhRWclIfDD4jY8IbdCQ5-kllob-fhgdfdghfhdh'
}
mixed_unfiltered = {
'test1': 'https://discordapp.com/api/webhooks/12412421412412/6h4_yshmNDKktdT-0VevOhqdXG9rDhR12412412414Q5-kllob-kI2jAxCZ5PdIn',
'test2': 'https://discordapp.com/api/webhooks/529617352682110997/6h4_yshmNDKktdT-0VevOhqdXG912412412412IbdCQ5-kllob-kI2jAxCZ5PdIn'
}
def create_embed(payload: dict) -> None:
# -------------------------------------------------------------------------
# Name of the product, URL of the product & New! or Restock! url
# -------------------------------------------------------------------------
embed = DiscordEmbed(
url=payload["link"],
description=payload["status"],
color=8149447
)
# -------------------------------------------------------------------------
# Image product
# -------------------------------------------------------------------------
embed.set_thumbnail(
url=payload["image"]
)
# -------------------------------------------------------------------------
# Store Name
# -------------------------------------------------------------------------
embed.add_embed_field(
name="Site",
value=f'{payload["store"]}'
)
# -------------------------------------------------------------------------
# The price of the product
# -------------------------------------------------------------------------
if payload.get("price"):
embed.add_embed_field(
name="Price",
value=payload["price"]
)
# -------------------------------------------------------------------------
# If store is Nike
# -------------------------------------------------------------------------
if "Nike" in payload["store"]:
if payload.get("nikeStatus"):
embed.add_embed_field(
name="\u200b",
value="\u200b"
)
embed.add_embed_field(
name="Status",
value=payload["nikeStatus"]
)
# -------------------------------------------------------------------------
# Nike Sales Channel
# -------------------------------------------------------------------------
if payload.get("salesChannel"):
embed.add_embed_field(
name="Sales Channel",
value="\n".join(payload["salesChannel"])
)
# -------------------------------------------------------------------------
# Sizes available
# Add extra spaces for sizes to make it cleaner for discord embed
# -------------------------------------------------------------------------
if payload.get("sizes"):
payload["stock"] = sum(v for v in payload["sizes"].values() if v)
payload["sizes"] = [f"{k} - ({v})" if v else k for k, v in payload["sizes"].items()]
# If we have stock in values then sum it up
embed.add_embed_field(
name="\u200b",
value="\u200b"
)
characterCount, i = 0, 0
for j, item in enumerate(payload["sizes"]):
# There is a limitation for Discord where if we reach over 1020 characters for one embed column.
# IT will throw a error. Now I check if the characters count is less than 900 then we create a new embed.
if len(item) + characterCount > 900:
embed.add_embed_field(
name="Sizes",
value="\n".join(payload["sizes"][i:j])
)
characterCount, i = len(item), j
else:
characterCount += len(item)
if characterCount:
embed.add_embed_field(
name="Sizes",
value="\n".join(payload["sizes"][i:])
)
embed.add_embed_field(
name="\u200b",
value="\u200b"
)
embed.add_embed_field(
name="\u200b",
value="\u200b"
)
# -------------------------------------------------------------------------
# If store is footlocker
# -------------------------------------------------------------------------
if "Footlocker" in payload["store"]:
if payload.get("stockLoaded"):
embed.add_embed_field(
name="Stock Loaded",
value=payload["stockLoaded"].upper()
)
if payload.get("styleCode"):
embed.add_embed_field(
name="\u200b",
value="\u200b"
)
embed.add_embed_field(
name="Style Code",
value=payload["styleCode"]
)
# -------------------------------------------------------------------------
# Release date for the product
# -------------------------------------------------------------------------
if payload.get("releaseDate"):
embed.add_embed_field(
name="Release Date",
value=payload["releaseDate"].to_datetime_string()
)
# -------------------------------------------------------------------------
# Stock keeping unit etc. 508214-660
# -------------------------------------------------------------------------
if payload.get("sku"):
embed.add_embed_field(
name="SKU",
value=payload["sku"]
)
# -------------------------------------------------------------------------
# Total stock of the product
# -------------------------------------------------------------------------
if payload.get("stock"):
embed.add_embed_field(
name="Total Stock",
value=payload["stock"]
)
# -------------------------------------------------------------------------
# Login/Cart/Checkout shortcut links
# -------------------------------------------------------------------------
embed.add_embed_field(
name="Shortcuts Links",
value=f'{" | ".join(shortcuts for shortcuts in payload["shortcut"])}'
)
# -------------------------------------------------------------------------
# Quick task for bots
# -------------------------------------------------------------------------
if payload.get("quicktask"):
embed.add_embed_field(
name="Quick Tasks",
value=f'{" | ".join(shortcuts for shortcuts in payload["quicktask"])}'
)
# -------------------------------------------------------------------------
# Footer timestamp
# -------------------------------------------------------------------------
embed.set_footer(
text=f'AutoSnkr | {pendulum.now("Europe/Stockholm").format("YYYY-MM-DD [[]HH:mm:ss.SSSS[]]")}'
)
# -------------------------------------------------------------------------
# Set title on the embed
# -------------------------------------------------------------------------
if payload.get('stock') and payload.get('name'):
embed.title = f'({payload["stock"]}) {payload["name"]}'
elif payload.get('name'):
embed.title = payload["name"]
else:
embed.title = payload.get('link')
# -------------------------------------------------------------------------
# Send payload/embed to Discord Notification function
# -------------------------------------------------------------------------
collection = mixed_filtered if payload["keyword"] else mixed_unfiltered
for region, discord_collection in collection.items():
webhook = DiscordWebhook(
url=discord_collection,
username="AutoSnkr Monitor",
)
webhook.add_embed(embed)
# Adding thread so each URL can post as fast as possible without needing to wait for each other
Thread(
target=post_embed,
args=(
payload,
region,
webhook
)
).start()
def post_embed(payload: Dict, region: str, webhook: DiscordWebhook) -> None:
success: bool = False
while not success:
try:
response = webhook.execute()
success = response.ok
# If we get a 429, retry after a short delay
if response.status_code == 429:
sleep_time = int(response.headers["retry-after"]) / 1000
logger.debug(f"Rate limit -> Retrying in {sleep_time} seconds")
time.sleep(sleep_time)
continue
# any response other than a 429 or a 200 OK is an error.
if not response.ok:
# FIXME Add discord notficiation and raise exception
pass
logger.info(f"Succesfully sent to Discord Reporter -> {region}")
except Exception as err:
# FIXME Add discord notficiation and raise exception
pass
if __name__ == '__main__':
create_embed(
{
"store": "Basket4ballers",
"link": "https://www.basket4ballers.com/en/pg/26471-nike-pg5-bred-cw3143-101.html",
"name": "Nike PG5 Bred",
"price": "EUR 119.9",
"image": "https://cdn1.basket4ballers.com/114821-large_default/nike-pg5-bred-cw3143-101.jpg",
"sizes": {
"[EU 38.5](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205049)": 1,
"[EU 39](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205052)": 1,
"[EU 40](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205055)": 3,
"[EU 40.5](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205058)": 4,
"[EU 41](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205061)": 9,
"[EU 42](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205064)": 11,
"[EU 42.5](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205067)": 11,
"[EU 43](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205070)": 16,
"[EU 44](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205073)": 21,
"[EU 44.5](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205076)": 15,
"[EU 45](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205079)": 20,
"[EU 45.5](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205082)": 7,
"[EU 46](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205085)": 17,
"[EU 47](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205088)": 7,
"[EU 47.5](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205091)": 5,
"[EU 48](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205094)": 3,
"[EU 48.5](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205097)": 2,
"[EU 49.5](https://www.basket4ballers.com/?controller=cart&add=1&as=true&qty=1&id_product=26471&token=e4d64f25476dcee4b08744d382dc405b&ipa=205100)": 1},
"shortcut": ["[Login](https://www.basket4ballers.com/en/authentification?back=my-account)",
"[Cart](https://www.basket4ballers.com/en/commande)",
"[Checkout Delivery](https://www.basket4ballers.com/en/commande?step=1)",
"[Checkout Shipping Service](https://www.basket4ballers.com/en/commande)",
"[Checkout PAyment](https://www.basket4ballers.com/en/commande)"],
"webhook": "mixed",
"status": "Restock!",
"keyword": True
}
)
The mock data is at the very bottom but in the future I will instead send the payload to the function.
I wonder what can I do to try to have less code but that still does the job. I feel like there should be a way more cleaner way to do this than what I did but looking forward to see what can be improved :)
Let me know if there is any missing information. The script should be runnable by copy pasting it but make sure to create your own discord webhooks to test the embed. I will unfortunately need to modify them so no one can spam me :)