import os
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from openai import OpenAI
import time
from datetime import datetime,timedelta
import threading
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
def is_logged_in(driver):
try:
driver.find_element(By.CSS_SELECTOR, "a.p-navgroup-link--user")
return True # connecté
except NoSuchElementException:
return False # déconnecté
def to_latest(UR):
if not UR.endswith("/latest"):
return UR.rstrip("/") + "/latest"
return UR
def delunread(url):
return url.removesuffix("/unread")
title =""
def siteweb(URL):
# Options Chrome
options = Options()
# Lancer le navigateur
driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install()),
options=options
)
newurl = to_latest(URL)
driver.get(newurl)
time.sleep(5) # temps pour charger le JavaScript
# Récupérer le HTML rendu
html = driver.page_source
driver.quit()
# Analyse HTML
soup = BeautifulSoup(html, "html.parser")
global title
# Sélectionne les messages
posts = soup.find_all("article", class_="message")
titre = soup.find("h1", class_="p-title-value")
title = titre.get_text(strip=True)
print(title)
n = 0
# Écriture dans le fichier texte
with open("adoasis.txt", "w", encoding="utf-8") as f:
f.write(f"Titre du topic : {title}\n")
for i, post in enumerate(posts, start=1):
content = post.find("div", class_="bbWrapper")
texte = content.get_text(separator="\n", strip=True) if content else ""
# pseudo normal OU anonyme
user_tag = post.find(
["a", "span"],
class_=["username", "username--anonymous"]
)
if user_tag:
username = user_tag.get_text(strip=True)
else:
username = "Anonyme"
f.write("-" * 50 + "\n")
f.write(f"Message {i}\n")
f.write(f"Utilisateur : {username}\n")
f.write(texte + "\n")
n += 1
if len(posts)== n :
return username != "Bobby_(bot)"
def chatgpt(fichier, max_retry=5):
for attempt in range(1, max_retry + 1):
try:
with open(fichier, "r", encoding="utf-8") as f:
contenu = f.read()
response = client.chat.completions.create(
model="gpt-4.1-mini",
messages=[
{
"role": "system",
"content": (
"Règle numéro 1 : pas de smiley"
"Tu es un membre actif d'un forum francophone, tu réponds au sujet dédié à te poser des questions"
"Tu écris comme un humain, de façon naturelle mais sans aller droit au but. "
"Tu ne dis jamais que tu es une IA. "
"Ton maitre est Loup007A"
"Tu réponds comme dans un fil de discussion,au dernier message "
"Les balises à utiliser pour tes messages sont : "
"[B], [I], [U], [S], [COLOR], [FONT], [SIZE], [URL]. pour les fermer met un / après la première ["
"La balise pour citer d'autres messages est : [QUOTE=\"username,post:\"] et se termine comme les autres"
"Sans introduction ni conclusion formelle. "
"Pour mentionner quelqu'un, mets @ devant son pseudo. "
"Utilise un langage courant, pas de gros mots ni familier."
"Réponds prioritairement aux messages de demande d'aide."
)
},
{
"role": "user",
"content": (
"Voici le contenu du fil de discussion :\n\n"
f"{contenu}\n\n"
"Réponds comme si tu étais un participant du forum, met en valeur les demandes d'aide prioritairement."
)
}
],
timeout=60
)
return response.choices[0].message.content
except Exception as e:
print(f"[OpenAI ERROR] tentative {attempt}/{max_retry} :", e)
# délais intelligents
msg = str(e).lower()
if "rate limit" in msg or "429" in msg:
time.sleep(15400)
elif "token" in msg or "context" in msg:
time.sleep(15400)
else:
time.sleep(30)
print("[OpenAI] abandon après trop d'échecs")
return None
def login(driver, username, password):
driver.get("https://adoasis.fr/login")
wait = WebDriverWait(driver, 15)
user_input = wait.until(EC.presence_of_element_located((By.NAME, "login")))
pass_input = driver.find_element(By.NAME, "password")
user_input.send_keys(username)
pass_input.send_keys(password)
pass_input.send_keys(Keys.RETURN)
time.sleep(5) # laisser le temps à la session de s'établir
def ouvrir():
options = Options()
driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install()),
options=options
)
return driver
def repondre(driver, topic_url):
# Forcer l'ouverture de l'éditeur de réponse
reply_url = topic_url + "/reply"
driver.get(reply_url)
wait = WebDriverWait(driver, 30)
# attendre que l'éditeur existe
wait.until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, "div.fr-element.fr-view[contenteditable='true']")
)
)
def ecriremessage(driver, message):
wait = WebDriverWait(driver, 30)
editor = wait.until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, "div.fr-element.fr-view[contenteditable='true']")
)
)
editor.click()
editor.send_keys(Keys.CONTROL, "a")
editor.send_keys(Keys.BACKSPACE)
# taper lentement pour déclencher les events JS
for char in message:
editor.send_keys(char)
time.sleep(0.0000005)
# événement final
editor.send_keys(" ")
def envoyerlemessage(driver):
wait = WebDriverWait(driver, 15)
submit = wait.until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, "button.button--icon--reply[type='submit']")
)
)
submit.click()
time.sleep(5)
def logout(driver):
driver.get("https://adoasis.fr/")
wait = WebDriverWait(driver, 15)
# Ouvre le menu utilisateur (avatar / pseudo)
user_menu = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "a.p-navgroup-link--user"))
)
user_menu.click()
time.sleep(1)
# Cliquer sur "Déconnexion"
logout_link = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "a[href*='logout']"))
)
logout_link.click()
time.sleep(3)
def clean_message(text):
text = text.replace("\r", "")
text = text.replace("\u200b", "")
text = text.replace("\u2028", "\n")
text = text.replace("\xa0", " ")
return text.strip()
API_KEY = os.environ["OPENAI_API_KEY"]
client = OpenAI(api_key=API_KEY)
PASSWORD = os.environ["ADOASIS_PASSWORD"]
USERNAME = os.environ["ADOASIS_USERNAME"]
def allin(link):
for i in range(1):
if siteweb(link) :
global title
if "Anglais" in title :
print("anglais,accès refusé")
break
print("debut")
driver = ouvrir()
driver.get("https://adoasis.fr")
login(driver, USERNAME, PASSWORD)
repondre(driver, link)
message = chatgpt("adoasis.txt")
if not message:
print("[OpenAI] message vide, on annule")
with open("messagesgpt.txt", "a+", encoding="utf-8") as f:
f.write("-"*50 + f"\n {link} : message annulé")
return
message = clean_message(message)
with open("messagesgpt.txt", "a+", encoding="utf-8") as f:
f.write("-"*50 + f"\n {link} : \n {message} \n")
ecriremessage(driver, message)
envoyerlemessage(driver)
print("-"*50 + f"\n le message :\n\n{message} a bien été envoyé à l'url suivante : \n{link}"+ "-"*50)
driver.quit()
"""
def cherche():
options = Options()
# Lancer le navigateur
driver = webdriver.Chrome(
service=Service(ChromeDriverManager().install()),
options=options
)
login(driver,USERNAME,PASSWORD)
driver.get("https://adoasis.fr/whats-new")
# Récupérer le HTML rendu
html = driver.page_source
driver.quit()
soup = BeautifulSoup(html, "html.parser")
topics = soup.select("div.structItem--thread")
lisst = []
for topic in topics:
a = topic.select_one("div.structItem-title a")
if not a:
continue
title = a.get_text(strip=True)
url = "https://adoasis.fr" + a["href"]
print(title, "->", url)
urln = delunread(url)
lisst.append(urln)
return lisst
"""
# Planning : jour -> [(heure_début, heure_fin), ...]
# weekday(): Monday=0 ... Sunday=6
PLANNING = {
0: [(16, 19), (20, 22)], # Lundi
1: [(14, 15), (19, 20)], # Mardi
2: [(8, 9), (17, 19)], # Mercredi
3: [(20, 21), (22, 23)], # Jeudi
4: [(21, 22), (23, 24)], # Vendredi
5: [(11, 12), (18, 20)], # Samedi
6: [(1,3), (22, 23)], # Dimanche
}
site = ""
def is_in_time_slot(hour, slots):
return any(start <= hour < end for start, end in slots)
def execute_action():
global site
allin(site)
# Alignement initial
while True :
if datetime.now().minute % 1 == 0 :
print("lancement du programme")
boucle = 0
while True:
now = datetime.now()
day = now.weekday()
hour = now.hour + now.minute / 60
boucle += 1
print(f"lancement de la boucle : {boucle}.")
if day in PLANNING and is_in_time_slot(hour, PLANNING[day]):
print("autorisé, lancement du bot :")
print("3")
time.sleep(1)
print("2")
time.sleep(1)
print("1")
execute_action()
else :
print("refusé, boucle suivante")
time.sleep(600)