import html
import logging
import re
import time
import requests
from env_config import (
DISCORD_ENABLED,
DISCORD_ROLE_MAP,
DISCORD_SERVER_NAME,
DISCORD_WEBHOOK_URL,
TELEGRAM_BOT_TOKEN,
TELEGRAM_CHAT_ID,
TELEGRAM_ENABLED,
TEST_MODE,
buy_now,
currency,
footer,
imminent_drop,
in_stock_title,
out_of_stock_title,
price_label,
sku_change_title,
sku_description,
time_label,
)
AVATAR = "https://git.djeex.fr/Djeex/nvidia-stock-bot/raw/branch/main/assets/img/ds_wh_pp.jpg"
THUMBNAIL = "https://git.djeex.fr/Djeex/nvidia-stock-bot/raw/branch/main/assets/img/RTX5000.jpg"
_MD_LINK = re.compile(r"\[([^\]]*)\]\(([^)\s]*)\)")
_MD_BOLD = re.compile(r"\*\*(.+?)\*\*")
_MD_CODE = re.compile(r"`(.+?)`")
_EMOJI_SHORTCODES = {":point_right:": "👉"}
def _md_to_telegram_html(text):
"""Convert the Discord markdown of the translations to Telegram HTML."""
text = html.escape(text)
text = _MD_LINK.sub(lambda m: f'{m.group(1)}', text)
text = _MD_BOLD.sub(lambda m: f"{m.group(1)}", text)
text = _MD_CODE.sub(lambda m: f"{m.group(1)}", text)
for shortcode, emoji in _EMOJI_SHORTCODES.items():
text = text.replace(shortcode, emoji)
return text
# In stock
def send_discord_notification(gpu_name, product_link, products_price):
if not DISCORD_ENABLED:
return
timestamp = int(time.time())
if TEST_MODE:
logging.info(f"[TEST MODE] Notification: {gpu_name} available!")
return
embed = {
"title": in_stock_title.format(gpu_name=gpu_name),
"color": 3066993,
"thumbnail": {"url": THUMBNAIL},
"author": {"name": "Nvidia Founder Editions"},
"fields": [
{"name": price_label, "value": f"`{currency}{products_price}`", "inline": True},
{"name": time_label, "value": f" ", "inline": True},
],
"description": buy_now.format(product_link=product_link),
"footer": {
"text": footer.format(DISCORD_SERVER_NAME=DISCORD_SERVER_NAME),
"icon_url": AVATAR,
},
}
payload = {
"content": DISCORD_ROLE_MAP.get(gpu_name, "@everyone"),
"username": "NviBot",
"avatar_url": AVATAR,
"embeds": [embed],
}
try:
response = requests.post(DISCORD_WEBHOOK_URL, json=payload)
if response.status_code == 204:
logging.info("✅ Notification sent to Discord.")
else:
logging.error(f"❌ Webhook error: {response.status_code} - {response.text}")
except Exception as e:
logging.error(f"🚨 Error sending webhook: {e}")
# Out of stock
def send_out_of_stock_notification(gpu_name, product_link, products_price):
if not DISCORD_ENABLED:
return
timestamp = int(time.time())
if TEST_MODE:
logging.info(f"[TEST MODE] Out of stock: {gpu_name}")
return
embed = {
"title": out_of_stock_title.format(gpu_name=gpu_name),
"color": 15158332,
"thumbnail": {"url": THUMBNAIL},
"url": product_link,
"author": {"name": "Nvidia Founder Editions"},
"footer": {
"text": footer.format(DISCORD_SERVER_NAME=DISCORD_SERVER_NAME),
"icon_url": AVATAR,
},
"fields": [
{"name": time_label, "value": f" ", "inline": True}
],
}
payload = {"username": "NviBot", "avatar_url": AVATAR, "embeds": [embed]}
try:
response = requests.post(DISCORD_WEBHOOK_URL, json=payload)
if response.status_code == 204:
logging.info("✅ Out-of-stock notification sent.")
else:
logging.error(f"❌ Webhook error: {response.status_code} - {response.text}")
except Exception as e:
logging.error(f"🚨 Error sending webhook: {e}")
# SKU change
def send_sku_change_notification(gpu_name, old_sku, new_sku, product_link):
if not DISCORD_ENABLED:
return
timestamp = int(time.time())
if TEST_MODE:
logging.info(f"[TEST MODE] SKU change: {old_sku} → {new_sku}")
return
embed = {
"title": sku_change_title.format(gpu_name=gpu_name),
"url": product_link,
"description": sku_description.format(old_sku=old_sku, new_sku=new_sku),
"color": 16776960,
"footer": {
"text": footer.format(DISCORD_SERVER_NAME=DISCORD_SERVER_NAME),
"icon_url": AVATAR,
},
"fields": [
{"name": time_label, "value": f" ", "inline": True}
],
}
payload = {
"content": imminent_drop.format(DISCORD_ROLE=DISCORD_ROLE_MAP.get(gpu_name, "@everyone")),
"username": "NviBot",
"avatar_url": AVATAR,
"embeds": [embed],
}
try:
response = requests.post(DISCORD_WEBHOOK_URL, json=payload)
if response.status_code == 204:
logging.info("✅ SKU change notification sent.")
else:
logging.error(f"❌ Webhook error: {response.status_code} - {response.text}")
except Exception as e:
logging.error(f"🚨 Error sending webhook: {e}")
# Telegram
def _send_telegram(text, success_log):
if TEST_MODE:
logging.info(f"[TEST MODE] Telegram message: {text}")
return
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
payload = {
"chat_id": TELEGRAM_CHAT_ID,
"text": text,
"parse_mode": "HTML",
"disable_web_page_preview": True,
}
try:
response = requests.post(url, json=payload, timeout=10)
if response.status_code == 200:
logging.info(success_log)
else:
logging.error(f"❌ Telegram error: {response.status_code} - {response.text}")
except Exception as e:
# The exception message may contain the bot token (it is part of the URL)
logging.error(f"🚨 Error sending Telegram message: {type(e).__name__}")
def _telegram_footer():
return html.escape(footer.format(DISCORD_SERVER_NAME=DISCORD_SERVER_NAME))
def _telegram_time():
return html.escape(time.strftime("%Y-%m-%d %H:%M:%S %Z"))
def send_telegram_notification(gpu_name, product_link, products_price):
if not TELEGRAM_ENABLED:
return
title = html.escape(in_stock_title.format(gpu_name=gpu_name))
description = _md_to_telegram_html(buy_now.format(product_link=product_link))
price = html.escape(f"{currency}{products_price}")
text = (
f"{title}\n"
f"{description}\n\n"
f"{html.escape(price_label)}: {price}\n"
f"{html.escape(time_label)}: {_telegram_time()}\n\n"
f"{_telegram_footer()}"
)
_send_telegram(text, "✅ Notification sent to Telegram.")
def send_telegram_out_of_stock_notification(gpu_name, product_link, products_price):
if not TELEGRAM_ENABLED:
return
title = html.escape(out_of_stock_title.format(gpu_name=gpu_name))
text = (
f'{title}\n'
f"{html.escape(time_label)}: {_telegram_time()}\n\n"
f"{_telegram_footer()}"
)
_send_telegram(text, "✅ Out-of-stock notification sent to Telegram.")
def send_telegram_sku_change_notification(gpu_name, old_sku, new_sku, product_link):
if not TELEGRAM_ENABLED:
return
alert = html.escape(imminent_drop.format(DISCORD_ROLE="").strip())
title = html.escape(sku_change_title.format(gpu_name=gpu_name))
description = _md_to_telegram_html(
sku_description.format(old_sku=old_sku, new_sku=new_sku)
)
text = (
f"{alert}\n"
f'{title}\n'
f"{description}\n"
f"{html.escape(time_label)}: {_telegram_time()}\n\n"
f"{_telegram_footer()}"
)
_send_telegram(text, "✅ SKU change notification sent to Telegram.")