1st commit
This commit is contained in:
commit
40d23113f7
35
Dockerfile
Normal file
35
Dockerfile
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Utilise une image officielle de Python avec les outils nécessaires
|
||||||
|
FROM python:3.9-slim
|
||||||
|
|
||||||
|
# Installe les dépendances requises pour Selenium et Chrome
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
curl unzip wget xvfb \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Télécharge et installe Google Chrome
|
||||||
|
RUN wget -qO- https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /usr/share/keyrings/google-keyring.gpg \
|
||||||
|
&& echo "deb [signed-by=/usr/share/keyrings/google-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | tee /etc/apt/sources.list.d/google-chrome.list \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y google-chrome-stable \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Télécharge et installe le ChromeDriver correspondant
|
||||||
|
RUN CHROME_VERSION=$(google-chrome --version | awk '{print $3}' | cut -d '.' -f 1) \
|
||||||
|
&& wget -O /tmp/chromedriver.zip "https://chromedriver.storage.googleapis.com/${CHROME_VERSION}.0/chromedriver_linux64.zip" \
|
||||||
|
&& unzip /tmp/chromedriver.zip -d /usr/local/bin/ \
|
||||||
|
&& rm /tmp/chromedriver.zip \
|
||||||
|
&& chmod +x /usr/local/bin/chromedriver
|
||||||
|
|
||||||
|
# Définit le répertoire de travail
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copie les fichiers nécessaires
|
||||||
|
COPY requirements.txt .
|
||||||
|
COPY .env .
|
||||||
|
COPY Nvidia_Stock_Checker.py ./script.py # Adapte le nom du fichier si nécessaire
|
||||||
|
|
||||||
|
# Installe les dépendances Python
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Commande pour exécuter le script
|
||||||
|
CMD ["python", "script.py"]
|
20
docker/.env
Normal file
20
docker/.env
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# URL de la page Nvidia à surveiller
|
||||||
|
URL="https://marketplace.nvidia.com/fr-fr/consumer/graphics-cards/?locale=fr-fr&page=1&limit=12&gpu=RTX%205090&manufacturer=NVIDIA&manufacturer_filter=NVIDIA~1"
|
||||||
|
|
||||||
|
# Nombre de cycles de vérification avant d'arrêter (1 = une seule vérification)
|
||||||
|
ITER_CYCLES=1
|
||||||
|
|
||||||
|
# Temps d'attente après le chargement de la page (en secondes)
|
||||||
|
WAIT_TIME=3
|
||||||
|
|
||||||
|
# Intervalle entre chaque vérification (en secondes)
|
||||||
|
RUN_INTERVAL=30
|
||||||
|
|
||||||
|
# Afficher le body HTML de la page pour débogage (TRUE/FALSE)
|
||||||
|
PRINT_BODY=FALSE
|
||||||
|
|
||||||
|
# Activer les alertes en cas d'erreur (TRUE/FALSE)
|
||||||
|
ERROR_ALERT=FALSE
|
||||||
|
|
||||||
|
# Webhook Discord pour envoyer des notifications en cas de stock disponible
|
||||||
|
DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/XXXXXX/XXXXXXXXX"
|
0
docker/compose.yml
Normal file
0
docker/compose.yml
Normal file
122
nvidia-stock-bot.py
Normal file
122
nvidia-stock-bot.py
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
from selenium import webdriver
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.chrome.options import Options
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# Charger les variables d'environnement depuis le fichier .env
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
URL_NVIDIA = os.getenv(
|
||||||
|
"URL",
|
||||||
|
"https://marketplace.nvidia.com/fr-fr/consumer/graphics-cards/?locale=fr-fr&page=1&limit=12&gpu=RTX%205090&manufacturer=NVIDIA&manufacturer_filter=NVIDIA~1"
|
||||||
|
)
|
||||||
|
|
||||||
|
N = int(os.getenv("ITER_CYCLES", 1))
|
||||||
|
WAIT_TIME = int(os.getenv("WAIT_TIME", 3))
|
||||||
|
RUN_INTERVAL = int(os.getenv("RUN_INTERVAL", 30))
|
||||||
|
PRINT_BODY = os.getenv("PRINT_BODY", "FALSE").lower() == "true"
|
||||||
|
ERROR_ALERT = os.getenv("ERROR_ALERT", "FALSE").lower() == "true"
|
||||||
|
DISCORD_WEBHOOK_URL = os.getenv("DISCORD_WEBHOOK_URL", "")
|
||||||
|
|
||||||
|
# Variable pour stocker l'état du stock (évite les notifications répétées)
|
||||||
|
previous_stock_state = False # False = hors stock, True = en stock
|
||||||
|
|
||||||
|
def send_discord_message(message: str):
|
||||||
|
if not DISCORD_WEBHOOK_URL:
|
||||||
|
print("Aucun webhook Discord défini (DISCORD_WEBHOOK_URL).")
|
||||||
|
return
|
||||||
|
|
||||||
|
data = {"content": message}
|
||||||
|
try:
|
||||||
|
response = requests.post(DISCORD_WEBHOOK_URL, json=data)
|
||||||
|
if response.status_code >= 400:
|
||||||
|
print(f"Erreur lors de l'envoi du message Discord : {response.text}")
|
||||||
|
else:
|
||||||
|
print("Message Discord envoyé avec succès.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Exception lors de l'envoi du message Discord : {e}")
|
||||||
|
|
||||||
|
def check_stock_button(driver):
|
||||||
|
"""
|
||||||
|
Vérifie si le bouton indiquant une rupture de stock est présent.
|
||||||
|
Retourne True si stock disponible, False sinon.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
out_of_stock_buttons = driver.find_elements(By.XPATH, "//button[contains(@class, 'stock-grey-out')]")
|
||||||
|
return not bool(out_of_stock_buttons)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erreur lors de la vérification du stock : {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def checkStockNvidia():
|
||||||
|
global previous_stock_state
|
||||||
|
|
||||||
|
chrome_options = Options()
|
||||||
|
chrome_options.add_argument("--headless")
|
||||||
|
chrome_options.add_argument("--no-sandbox")
|
||||||
|
chrome_options.add_argument("--disable-gpu")
|
||||||
|
chrome_options.add_argument("--disable-notifications")
|
||||||
|
chrome_options.add_argument("--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
|
||||||
|
|
||||||
|
driver = webdriver.Chrome(options=chrome_options)
|
||||||
|
|
||||||
|
for i in range(N):
|
||||||
|
try:
|
||||||
|
driver.get(URL_NVIDIA)
|
||||||
|
time.sleep(WAIT_TIME) # Attente fixe après chargement de la page
|
||||||
|
|
||||||
|
if PRINT_BODY:
|
||||||
|
print("===== BODY START =====")
|
||||||
|
print(driver.page_source)
|
||||||
|
print("===== BODY END =====")
|
||||||
|
|
||||||
|
is_available = check_stock_button(driver)
|
||||||
|
|
||||||
|
if is_available and not previous_stock_state:
|
||||||
|
message = {
|
||||||
|
"title": f"🚀 RTX 5090 FE en stock !",
|
||||||
|
"description": f":point_right: **[Achetez ici](https://marketplace.nvidia.com/fr-fr/consumer/graphics-cards/?locale=fr-fr&page=1&limit=12&gpu=RTX%205090,RTX%205080&manufacturer=NVIDIA)**",
|
||||||
|
"color": 3066993, # Couleur verte
|
||||||
|
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime()),
|
||||||
|
#"thumbnail": {
|
||||||
|
# "url": "https://www.nvidia.com/content/dam/en-zz/Solutions/geforce/graphic-cards/50-series/rtx-5090/geforce-rtx-5090-learn-more-og-1200x630.jpg"
|
||||||
|
#}
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"content": "@everyone",
|
||||||
|
"username": "Nvidia Bot",
|
||||||
|
"embeds": [message]
|
||||||
|
}
|
||||||
|
|
||||||
|
send_discord_message(message)
|
||||||
|
previous_stock_state = True # Met à jour l'état du stock
|
||||||
|
elif not is_available:
|
||||||
|
previous_stock_state = False # Remet à zéro pour permettre une future notification
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("ERREUR DURANT UNE VÉRIFICATION :")
|
||||||
|
traceback.print_exc()
|
||||||
|
if ERROR_ALERT:
|
||||||
|
send_discord_message(f"Erreur dans le script :\n```\n{traceback.format_exc()}\n```")
|
||||||
|
|
||||||
|
driver.quit()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(f"Script démarré. Vérification toutes les {RUN_INTERVAL} secondes...")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
checkStockNvidia()
|
||||||
|
except Exception as e:
|
||||||
|
print("ERREUR GLOBALE : ")
|
||||||
|
traceback.print_exc()
|
||||||
|
if ERROR_ALERT:
|
||||||
|
send_discord_message(f"Erreur globale dans le script :\n```\n{traceback.format_exc()}\n```")
|
||||||
|
|
||||||
|
print(f"Prochaine vérification dans {RUN_INTERVAL} secondes...")
|
||||||
|
time.sleep(RUN_INTERVAL)
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
selenium
|
||||||
|
python-dotenv
|
||||||
|
requests
|
Loading…
x
Reference in New Issue
Block a user