1st commit
This commit is contained in:
		
							
								
								
									
										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
 | 
				
			||||||
		Reference in New Issue
	
	Block a user