diff --git a/.env.example b/.env.example index 580d5bc..1b5404b 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ TOKEN='your_discord_bot_toke' RAPIDAPI_KEY='your_rapidapi_key' -RAPIDAPI_KEY2='your_rapidapi_key2' \ No newline at end of file +RAPIDAPI_KEY2='your_rapidapi_key2' +QUERY_INTERNSHIP='your_query_internship' +QUERY_FULLTIME='your_query_fulltime' \ No newline at end of file diff --git a/.idea/bot-discord-zone01.iml b/.idea/bot-discord-zone01.iml index f1deaca..ba5cb7b 100644 --- a/.idea/bot-discord-zone01.iml +++ b/.idea/bot-discord-zone01.iml @@ -1,7 +1,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index 812ab5a..ad7d1b8 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/bot.py b/bot.py index 26aaf7a..2a5e412 100644 --- a/bot.py +++ b/bot.py @@ -13,7 +13,8 @@ bot = commands.Bot(command_prefix="!", intents=intents) -initial_extensions = ['cogs.gestion_ping', 'cogs.gestion_jobs', 'cogs.gestion_cdi', 'cogs.event_cog', 'cogs.helped_student', 'cogs.embed_cog'] +initial_extensions = ['cogs.gestion_ping', 'cogs.gestion_jobs', 'cogs.gestion_cdi', 'cogs.event_cog', + 'cogs.helped_student', 'cogs.embed_cog', 'cogs.query_cog'] # Flag to check if the bot is loading for the first time first_ready = True @@ -73,6 +74,37 @@ async def on_close(): print("Bot disconnected from Discord.") +# Ajoutez ce gestionnaire d'erreurs globalement dans votre fichier principal +# Gestionnaire d'événements pour les erreurs globales +@bot.event +async def on_command_error(ctx, error): + if isinstance(error, commands.CommandNotFound): + embed = discord.Embed( + title="🚫 Commande Inconnue", + description="La commande que vous avez essayée n'existe pas. Veuillez vérifier la commande et réessayer.", + color=discord.Color.red() + ) + embed.set_footer(text="Utilisez !help pour voir les commandes disponibles.") + await ctx.send(embed=embed) + elif isinstance(error, commands.CommandInvokeError): + # Gestion d'erreurs spécifiques + embed = discord.Embed( + title="❌ Erreur d'Exécution", + description="Une erreur s'est produite lors de l'exécution de la commande. Veuillez réessayer plus tard.", + color=discord.Color.red() + ) + embed.set_footer(text="Veuillez vérifier et réessayer.") + await ctx.send(embed=embed) + else: + embed = discord.Embed( + title="❌ Erreur", + description=str(error), + color=discord.Color.red() + ) + embed.set_footer(text="Veuillez vérifier la commande et réessayer.") + await ctx.send(embed=embed) + + attributes = { 'name': "help", 'aliases': ["helpme"], diff --git a/cogs/gestion_cdi.py b/cogs/gestion_cdi.py index 94b1030..e9ec2de 100644 --- a/cogs/gestion_cdi.py +++ b/cogs/gestion_cdi.py @@ -6,9 +6,8 @@ from utils.config_loader import role_ping_cdi, forum_channel_id_cdi, guild_id from utils.cdi_fetcher import fetch_api_fulltime - class CDICog(commands.Cog): - """Cog pour la gestion des offres d'emploi.""" + """Cog pour la gestion des offres d'emploi CDI.""" def __init__(self, bot): self.bot = bot @@ -25,8 +24,6 @@ async def send_cdilist(self, ctx=None, loading_message=None): return forum_channel_cdi = guild.get_channel(forum_channel_id_cdi) - # forum_channel_cdi = ctx.guild.get_channel(forum_channel_id_cdi) - if isinstance(forum_channel_cdi, discord.ForumChannel): # Obtenir les threads actifs et archivés existants active_threads = forum_channel_cdi.threads @@ -37,35 +34,67 @@ async def send_cdilist(self, ctx=None, loading_message=None): all_threads = active_threads + archived_threads - list_jobs = await fetch_api_fulltime() + list_jobs, query_message = await fetch_api_fulltime(self.bot) + + # Vérification si aucune query n'a été initialisée + if "Aucune query n'a été définie" in query_message: + if ctx: + if loading_message: + embed_error = discord.Embed( + title="🚫 Erreur : Query Non Initialisée", + description="Aucune query n'a été définie. Veuillez initialiser une query avec `!setqueryFulltime`.", + color=discord.Color.red() + ) + embed_error.set_footer(text="Veuillez configurer une query pour continuer.") + await loading_message.edit(embed=embed_error) + return # Arrêter la fonction si la query n'est pas définie + else: + channel_id = 1257310056546963479 # Remplace par l'ID de ton channel + channel = self.bot.get_channel(channel_id) + if channel: + embed_error = discord.Embed( + title="⚠️ Erreur Automatique", + description="La tâche automatique n'a pas pu s'exécuter car aucune query n'a été définie. Veuillez configurer une query avec `!setqueryFulltime`.", + color=discord.Color.red() + ) + await channel.send(embed=embed_error) + return + await asyncio.sleep(1) verif = False if ctx: if not list_jobs: - await ctx.send("Aucune nouvelle offre d'emploi pour les apprenants.") + embed_no_jobs = discord.Embed( + title="🔍 Aucune Nouvelle Offre", + description="Aucune nouvelle offre d'emploi pour les contrats à temps plein n'a été trouvée.", + color=discord.Color.greyple() + ) + embed_no_jobs.set_footer(text="Vérifiez plus tard pour les nouvelles offres.") + await ctx.send(embed=embed_no_jobs) verif = True if verif: if loading_message: - # Modifier l'embed de chargement pour indiquer la fin de la mise à jour embed_updated = discord.Embed( - title="Erreur lors de la mise à jour", - description=f"Aucune des listes d'offres d'emploi n'a pu être mise à jour. Veuillez " - f"réessayer plus tard.", + title="⚠️ Erreur lors de la Mise à Jour", + description="Aucune des listes d'offres d'emploi n'a pu être mise à jour. Veuillez réessayer plus tard.", color=discord.Color.red() ) + embed_updated.add_field( + name="Message de l'API", + value=query_message if query_message else "Aucune query n'a été définie.", + inline=False + ) await loading_message.edit(embed=embed_updated) return all_jobs = list_jobs - found_threads = [] new_threads_created = False for job in all_jobs: - title = job.get("job_title") company = job.get("employer_name") date = job.get("job_posted_at_datetime_utc") @@ -76,9 +105,13 @@ async def send_cdilist(self, ctx=None, loading_message=None): if title and link and company: thread_title = f"{company} - {title}" - if date and link: - thread_content = f"Bonjour <@&{role_ping_cdi}> ! Offre sur **{city}**, chez **{company}** qui recherche un développeur **{title}**.Pour plus de détails et pour postuler, cliquez sur le lien : {link}" + thread_content = ( + f"👋 Bonjour <@&{role_ping_cdi}> !\n\n" + f"🔎 Offre sur **{city}** chez **{company}**.\n" + f"📈 Poste recherché : **{title}**\n" + f"🔗 Pour plus de détails et pour postuler, cliquez sur le lien : [Postuler]({link})" + ) # Chercher un thread existant avec le même titre existing_thread = None @@ -90,7 +123,7 @@ async def send_cdilist(self, ctx=None, loading_message=None): # Si un thread avec le même titre existe déjà, passe au suivant if existing_thread: - print("Thread found:", existing_thread.name) + print("Thread trouvé :", existing_thread.name) continue # Créer le nouveau thread @@ -101,55 +134,63 @@ async def send_cdilist(self, ctx=None, loading_message=None): await asyncio.sleep(1) except discord.errors.HTTPException as e: if e.code == 429: - print( - "Rate limited by Discord, will try again later." - ) + print("Rate limited by Discord, retrying later.") break await asyncio.sleep(1) + # Vérifier si aucun nouveau thread n'a été créé if not new_threads_created: if loading_message: embed_updated = discord.Embed( - title="Aucune nouvelle offre", - description="Aucune nouvelle offre d'emploi n'a été trouvée.", + title="🔔 Aucune Nouvelle Offre", + description="Aucune nouvelle offre d'emploi n'a été trouvée pour les CDI.", color=discord.Color.green() ) + embed_updated.add_field( + name="Message de l'API", + value=query_message if query_message else "Aucune query n'a été définie.", + inline=False + ) await loading_message.edit(embed=embed_updated) else: if loading_message: embed_updated = discord.Embed( - title="Mise à jour terminée", + title="✅ Mise à Jour Complète", description="Toutes les nouvelles offres d'emploi ont été publiées avec succès.", color=discord.Color.blue() ) + embed_updated.add_field( + name="Message de l'API", + value=query_message if query_message else "Aucune query n'a été définie.", + inline=False + ) await loading_message.edit(embed=embed_updated) else: print("Le canal spécifié n'est pas un ForumChannel.") if loading_message: embed_updated = discord.Embed( - title="Erreur lors de la mise à jour", + title="❌ Erreur de Canal", description="Le canal spécifié n'est pas un ForumChannel.", color=discord.Color.red() ) await loading_message.edit(embed=embed_updated) - @commands.command(name='update_cdi') + @commands.command(name='update_fulltime', aliases=['update_cdi'], description="Force la mise à jour des offres d'emploi pour les CDI.") async def update_cdi(self, ctx): """Force la mise à jour des offres d'emploi pour les CDI.""" - # await ctx.send(f"Updated jobs list !") embed_loading = discord.Embed( - title="Mise à jour en cours", + title="🔄 Mise à Jour en Cours", description="La liste des offres d'emploi pour les CDI est en cours de mise à jour, veuillez patienter...", color=discord.Color.orange() ) embed_loading.set_thumbnail( - url="https://i.imgur.com/5AGlfwy.gif") # Lien vers une icône d'engrenage animée + url="https://i.imgur.com/5AGlfwy.gif" + ) # Lien vers une icône d'engrenage animée loading_message = await ctx.send(embed=embed_loading) await self.send_cdilist(ctx, loading_message) - # await ctx.send(f"Fini !") async def setup(bot): diff --git a/cogs/gestion_help.py b/cogs/gestion_help.py index c58cc76..1b1ca63 100644 --- a/cogs/gestion_help.py +++ b/cogs/gestion_help.py @@ -1,42 +1,80 @@ import discord - from discord.ext import commands +async def send_command_error(ctx, error): + if isinstance(error, commands.CommandNotFound): + embed = discord.Embed( + title="🚫 Commande Inconnue", + description="La commande que vous avez essayée n'existe pas. Veuillez vérifier la commande et réessayer.", + color=discord.Color.red() + ) + embed.set_footer(text="Utilisez !help pour voir les commandes disponibles.") + else: + embed = discord.Embed( + title="❌ Erreur", + description=str(error), + color=discord.Color.red() + ) + embed.set_footer(text="Veuillez vérifier la commande et réessayer.") + + await ctx.send(embed=embed) + + class SupremeHelpCommand(commands.Cog, commands.HelpCommand): def get_command_signature(self, command): return '%s%s %s' % (self.context.clean_prefix, command.qualified_name, command.signature) async def send_bot_help(self, mapping): - embed = discord.Embed(title="Help", color=discord.Color.blurple()) + embed = discord.Embed( + title="🔧 Commandes du Bot", + description="Voici toutes les commandes disponibles pour ce bot.", + color=discord.Color.blurple() + ) + embed.set_thumbnail(url="https://i.imgur.com/vn0HoFx.png") # Ajouter une image d'illustration + for cog, commands in mapping.items(): filtered = await self.filter_commands(commands, sort=True) - if command_signatures := [ - self.get_command_signature(c) for c in filtered - ]: - cog_name = getattr(cog, "qualified_name", "No Category") - embed.add_field(name=cog_name, value="\n".join(command_signatures), inline=False) + if filtered: + cog_name = getattr(cog, "qualified_name", "Aucune Catégorie") + command_list = "\n".join(f"`{self.get_command_signature(c)}`" for c in filtered) + embed.add_field(name=f"📁 {cog_name}", value=command_list, inline=False) channel = self.get_destination() await channel.send(embed=embed) async def send_command_help(self, command): - embed = discord.Embed(title=self.get_command_signature(command), color=discord.Color.blurple()) - if command.help: - embed.description = command.help + embed = discord.Embed( + title=self.get_command_signature(command), + description=command.help or "Aucune description disponible.", + color=discord.Color.blurple() + ) if alias := command.aliases: - embed.add_field(name="Aliases", value=", ".join(alias), inline=False) + embed.add_field(name="🔄 Alias", value=", ".join(alias), inline=False) + if command.cog: + embed.add_field(name="📁 Catégorie", value=command.cog.qualified_name, inline=False) + embed.set_footer(text="Pour plus d'informations sur d'autres commandes, utilisez !help") channel = self.get_destination() await channel.send(embed=embed) - async def send_help_embed(self, title, description, commands): # a helper function to add commands to an embed - embed = discord.Embed(title=title, description=description or "No help found...") + async def send_help_embed(self, title, description, commands): + embed = discord.Embed( + title=title, + description=description or "Aide non trouvée.", + color=discord.Color.blurple() + ) + embed.set_thumbnail(url="https://i.imgur.com/vn0HoFx.png") # Ajouter une image d'illustration if filtered_commands := await self.filter_commands(commands): for command in filtered_commands: - embed.add_field(name=self.get_command_signature(command), value=command.help or "No help found...") + embed.add_field( + name=self.get_command_signature(command), + value=command.help or "Aucune description disponible.", + inline=False + ) + embed.set_footer(text="Pour plus d'informations, utilisez !help") await self.get_destination().send(embed=embed) async def send_group_help(self, group): @@ -44,15 +82,9 @@ async def send_group_help(self, group): await self.send_help_embed(title, group.help, group.commands) async def send_cog_help(self, cog): - title = cog.qualified_name or "No" - await self.send_help_embed(f'{title} Category', cog.description, cog.get_commands()) - - async def send_error_message(self, error): - embed = discord.Embed(title="Error", description=error, color=discord.Color.red()) - channel = self.get_destination() - - await channel.send(embed=embed) + title = cog.qualified_name or "Aucune Catégorie" + await self.send_help_embed(f'📚 {title} Category', cog.description, cog.get_commands()) async def setup(bot): - await bot.add_cog(SupremeHelpCommand(bot)) + await bot.add_cog(SupremeHelpCommand(bot)) \ No newline at end of file diff --git a/cogs/gestion_jobs.py b/cogs/gestion_jobs.py index 862b99b..2cfd015 100644 --- a/cogs/gestion_jobs.py +++ b/cogs/gestion_jobs.py @@ -6,7 +6,6 @@ from utils.config_loader import role_p1_2023, role_p2_2023, forum_channel_id, guild_id from utils.intern_fetcher import fetch_api_intern - class JobCog(commands.Cog): """Cog pour la gestion des offres d'alternance.""" @@ -25,8 +24,6 @@ async def send_jobslist(self, ctx=None, loading_message=None): return forum_channel_job = guild.get_channel(forum_channel_id) - # forum_channel_job = ctx.guild.get_channel(forum_channel_id) - if isinstance(forum_channel_job, discord.ForumChannel): # Obtenir les threads actifs et archivés existants active_threads = forum_channel_job.threads @@ -37,7 +34,31 @@ async def send_jobslist(self, ctx=None, loading_message=None): all_threads = active_threads + archived_threads - list_jobs = await fetch_api_intern() + list_jobs, query_message = await fetch_api_intern(self.bot) + + # Vérification si aucune query n'a été initialisée + if "Aucune query n'a été définie" in query_message: + if ctx: + if loading_message: + embed_error = discord.Embed( + title="⚠️ Erreur : Query Non Initialisée", + description="Aucune query n'a été définie. Veuillez initialiser une query avec la commande `!setqueryIntern`.", + color=discord.Color.red() + ) + embed_error.set_footer(text="Veuillez configurer une query pour continuer.") + await loading_message.edit(embed=embed_error) + return # Arrêter la fonction si la query n'est pas définie + else: + channel_id = 1257310056546963479 # Remplace par l'ID de ton channel + channel = self.bot.get_channel(channel_id) + if channel: + embed_error = discord.Embed( + title="🚫 Erreur Automatique", + description="La tâche automatique n'a pas pu s'exécuter car aucune query n'a été définie. Veuillez configurer une query avec `!setqueryIntern`.", + color=discord.Color.red() + ) + await channel.send(embed=embed_error) + return # Arrêter la fonction si la query n'est pas définie await asyncio.sleep(1) @@ -45,28 +66,35 @@ async def send_jobslist(self, ctx=None, loading_message=None): if ctx: if not list_jobs: - await ctx.send("Aucune nouvelle offre d'emploi pour les alternants.") + embed_no_jobs = discord.Embed( + title="🔍 Aucune Nouvelle Offre", + description="Aucune nouvelle offre d'emploi pour les alternants n'a été trouvée.", + color=discord.Color.greyple() + ) + embed_no_jobs.set_footer(text="Vérifiez plus tard pour les nouvelles offres.") + await ctx.send(embed=embed_no_jobs) verif = True if verif: if loading_message: - # Modifier l'embed de chargement pour indiquer la fin de la mise à jour embed_updated = discord.Embed( - title="Erreur lors de la mise à jour", - description=f"Aucune des listes d'offres d'emploi n'a pu être mise à jour. Veuillez " - f"réessayer plus tard.", + title="⚠️ Erreur lors de la Mise à Jour", + description="Aucune des listes d'offres d'emploi n'a pu être mise à jour. Veuillez réessayer plus tard.", color=discord.Color.red() ) + embed_updated.add_field( + name="Message de l'API", + value=query_message if query_message else "Aucune query n'a été définie.", + inline=False + ) await loading_message.edit(embed=embed_updated) return all_jobs = list_jobs - found_threads = [] new_threads_created = False for job in all_jobs: - title = job.get("job_title") company = job.get("employer_name") date = job.get("job_posted_at_datetime_utc") @@ -77,9 +105,13 @@ async def send_jobslist(self, ctx=None, loading_message=None): if title and link and company: thread_title = f"{company} - {title}" - if date and link: - thread_content = f"Bonjour <@&{role_p1_2023}> et <@&{role_p2_2023}> ! Offre d'alternance sur **{city}**, chez **{company}** qui recherche un développeur **{title}**.Pour plus de détails et pour postuler, cliquez sur le lien : {link}" + thread_content = ( + f"👋 Bonjour <@&{role_p1_2023}> et <@&{role_p2_2023}> !\n\n" + f"🔎 Offre d'alternance sur **{city}** chez **{company}**.\n" + f"📈 Poste recherché : **{title}**\n" + f"🔗 Pour plus de détails et pour postuler, cliquez sur le lien : [Postuler]({link})" + ) # Chercher un thread existant avec le même titre existing_thread = None @@ -97,40 +129,50 @@ async def send_jobslist(self, ctx=None, loading_message=None): # Créer le nouveau thread try: thread = await forum_channel_job.create_thread( - name=thread_title, content=thread_content) + name=thread_title, content=thread_content + ) new_threads_created = True await asyncio.sleep(1) except discord.errors.HTTPException as e: if e.code == 429: - print( - "Rate limited by Discord, will try again later." - ) + print("Rate limited by Discord, will try again later.") break await asyncio.sleep(1) + # Vérifier si aucun nouveau thread n'a été créé if not new_threads_created: if loading_message: embed_updated = discord.Embed( - title="Aucune nouvelle offre", + title="🔔 Aucune Nouvelle Offre", description="Aucune nouvelle offre d'alternance n'a été trouvée.", color=discord.Color.green() ) + embed_updated.add_field( + name="Message de l'API", + value=query_message if query_message else "Aucune query n'a été définie.", + inline=False + ) await loading_message.edit(embed=embed_updated) else: if loading_message: embed_updated = discord.Embed( - title="Mise à jour terminée", + title="✅ Mise à Jour Terminée", description="Toutes les nouvelles offres d'alternance ont été publiées avec succès.", color=discord.Color.blue() ) + embed_updated.add_field( + name="Message de l'API", + value=query_message if query_message else "Aucune query n'a été définie.", + inline=False + ) await loading_message.edit(embed=embed_updated) else: print("Le canal spécifié n'est pas un ForumChannel.") if loading_message: embed_updated = discord.Embed( - title="Erreur lors de la mise à jour", + title="❌ Erreur de Canal", description="Le canal spécifié n'est pas un ForumChannel.", color=discord.Color.red() ) @@ -139,19 +181,17 @@ async def send_jobslist(self, ctx=None, loading_message=None): @commands.command(name='update_internships', aliases=['update_jobs'], description="Force la mise à jour des offres d'emploi pour les alternants.") async def update_job(self, ctx): """Force la mise à jour des offres d'emploi pour les alternants.""" - # await ctx.send(f"Updated jobs list !") embed_loading = discord.Embed( - title="Mise à jour en cours", - description="La liste des offres d'emploi pour l'alternance est en cours de mise à jour, veuillez patienter...", + title="🔄 Mise à Jour en Cours", + description="La liste des offres d'emploi pour l'alternance est en cours de mise à jour. Veuillez patienter...", color=discord.Color.orange() ) embed_loading.set_thumbnail( - url="https://i.imgur.com/5AGlfwy.gif") # Lien vers une icône d'engrenage animée + url="https://i.imgur.com/5AGlfwy.gif" # Lien vers une icône d'engrenage animée + ) loading_message = await ctx.send(embed=embed_loading) await self.send_jobslist(ctx, loading_message) - # await ctx.send(f"Fini !") - async def setup(bot): await bot.add_cog(JobCog(bot)) diff --git a/cogs/query_cog.py b/cogs/query_cog.py new file mode 100644 index 0000000..c8e4b49 --- /dev/null +++ b/cogs/query_cog.py @@ -0,0 +1,189 @@ +import discord +from discord.ext import commands +from utils.config_loader import query_intern, query_fulltime +from dotenv import set_key +from pathlib import Path + +class QueryCog(commands.Cog): + def __init__(self, bot): + self.bot = bot + self.query_intern = query_intern # Initialiser avec la variable depuis .env + self.query_fulltime = query_fulltime # Ajouter la variable pour fulltime + + @commands.command(name='setqueryIntern') + async def set_query_intern(self, ctx, query: str = None): + """Commande pour définir une query pour les stages.""" + if query is None: + embed = discord.Embed( + title="⚠️ Erreur : Query manquante", + description="Veuillez fournir une query pour définir une nouvelle valeur. Utilisez `!setqueryIntern `.", + color=discord.Color.red() + ) + await ctx.send(embed=embed) + return + + if not query.strip(): + embed = discord.Embed( + title="⚠️ Erreur : Query vide", + description="La query que vous avez fournie est vide. Veuillez entrer une query valide.", + color=discord.Color.red() + ) + await ctx.send(embed=embed) + return + + if query.strip() == "default": + # Réinitialiser la query à la valeur par défaut + self.query_intern = "Développeur full stack en France" # Mettre une valeur par défaut appropriée + env_path = Path('.') / '.env' + set_key(env_path, 'QUERY_INTERNSHIP', self.query_intern) + + embed = discord.Embed( + title="🔄 Query Réinitialisée", + description=f"La query a été réinitialisée à : **{self.query_intern}**", + color=discord.Color.green() + ) + await ctx.send(embed=embed) + return + + if query == self.query_intern: + embed = discord.Embed( + title="⚠️ Query Identique", + description="La query que vous avez fournie est identique à la query actuelle. Veuillez fournir une nouvelle query.", + color=discord.Color.red() + ) + await ctx.send(embed=embed) + return + + if len(query) > 100: + embed = discord.Embed( + title="⚠️ Query Trop Longue", + description="La query que vous avez fournie est trop longue. Veuillez fournir une query de 100 caractères ou moins.", + color=discord.Color.red() + ) + await ctx.send(embed=embed) + return + + # Mettre à jour la variable et le fichier .env + self.query_intern = query + env_path = Path('.') / '.env' + set_key(env_path, 'QUERY_INTERNSHIP', query) + + embed = discord.Embed( + title="✅ Query Initialisée", + description=f"La query a été définie comme : **{self.query_intern}**", + color=discord.Color.green() + ) + await ctx.send(embed=embed) + + @commands.command(name='showqueryIntern') + async def show_query_intern(self, ctx): + """Commande pour afficher la query actuelle pour les stages.""" + if not self.query_intern: + embed = discord.Embed( + title="❌ Aucune Query Définie", + description="Aucune query n'a été définie. Utilisez la commande `!setqueryIntern` pour en définir une.", + color=discord.Color.red() + ) + else: + embed = discord.Embed( + title="🔍 Query Actuelle", + description=f"La query actuelle est : **{self.query_intern}**", + color=discord.Color.blue() + ) + + await ctx.send(embed=embed) + + @commands.command(name='setqueryFulltime') + async def set_query_fulltime(self, ctx, query: str = None): + """Commande pour définir une query pour les emplois à temps plein.""" + if query is None: + embed = discord.Embed( + title="⚠️ Erreur : Query manquante", + description="Veuillez fournir une query pour définir une nouvelle valeur. Utilisez `!setqueryFulltime `.", + color=discord.Color.red() + ) + await ctx.send(embed=embed) + return + + if not query.strip(): + embed = discord.Embed( + title="⚠️ Erreur : Query vide", + description="La query que vous avez fournie est vide. Veuillez entrer une query valide.", + color=discord.Color.red() + ) + await ctx.send(embed=embed) + return + + if query.strip() == "default": + # Réinitialiser la query à la valeur par défaut + self.query_fulltime = "Développeur web senior en France" # Mettre une valeur par défaut appropriée + env_path = Path('.') / '.env' + set_key(env_path, 'QUERY_FULLTIME', self.query_fulltime) + + embed = discord.Embed( + title="🔄 Query Réinitialisée", + description=f"La query a été réinitialisée à : **{self.query_fulltime}**", + color=discord.Color.green() + ) + await ctx.send(embed=embed) + return + + if query == self.query_fulltime: + embed = discord.Embed( + title="⚠️ Query Identique", + description="La query que vous avez fournie est identique à la query actuelle. Veuillez fournir une nouvelle query.", + color=discord.Color.red() + ) + await ctx.send(embed=embed) + return + + if len(query) > 100: + embed = discord.Embed( + title="⚠️ Query Trop Longue", + description="La query que vous avez fournie est trop longue. Veuillez fournir une query de 100 caractères ou moins.", + color=discord.Color.red() + ) + await ctx.send(embed=embed) + return + + # Mettre à jour la variable et le fichier .env + self.query_fulltime = query + env_path = Path('.') / '.env' + set_key(env_path, 'QUERY_FULLTIME', query) + + embed = discord.Embed( + title="✅ Query Initialisée", + description=f"La query a été définie comme : **{self.query_fulltime}**", + color=discord.Color.green() + ) + await ctx.send(embed=embed) + + @commands.command(name='showqueryFulltime') + async def show_query_fulltime(self, ctx): + """Commande pour afficher la query actuelle pour les emplois à temps plein.""" + if not self.query_fulltime: + embed = discord.Embed( + title="❌ Aucune Query Définie", + description="Aucune query n'a été définie. Utilisez la commande `!setqueryFulltime` pour en définir une.", + color=discord.Color.red() + ) + else: + embed = discord.Embed( + title="🔍 Query Actuelle", + description=f"La query actuelle est : **{self.query_fulltime}**", + color=discord.Color.blue() + ) + + await ctx.send(embed=embed) + + def get_query_intern(self): + """Renvoie la valeur actuelle de query_intern.""" + return self.query_intern + + def get_query_fulltime(self): + """Renvoie la valeur actuelle de query_fulltime.""" + return self.query_fulltime + +# Fonction pour ajouter le Cog au bot +async def setup(bot): + await bot.add_cog(QueryCog(bot)) diff --git a/jobslist.py b/jobslist.py deleted file mode 100644 index dc1defb..0000000 --- a/jobslist.py +++ /dev/null @@ -1,83 +0,0 @@ -import imaplib -import email -from email.header import decode_header - - -# Connexion à la boîte de réception -def connect_to_email(username, password, imap_url): - mail = imaplib.IMAP4_SSL(imap_url) - mail.login(username, password) - mail.select("inbox") - return mail - - -# Extraction des informations des e-mails -def extract_job_info(mail, limit=50): - status, messages = mail.search(None, 'ALL') - job_infos = [] - target_email = "alert@indeed.com" - - # Limit the number of emails to process - email_nums = messages[0].split() - if len(email_nums) > limit: - email_nums = email_nums[-limit:] # Get the last `limit` number of emails - - for num in email_nums: - status, msg_data = mail.fetch(num, '(RFC822)') - msg = email.message_from_bytes(msg_data[0][1]) - - # Vérifier l'adresse de l'expéditeur - from_ = msg.get("From") - if from_: - from_email = email.utils.parseaddr(from_)[1] - if from_email.lower() != target_email.lower(): - continue # Passer au prochain e-mail si l'expéditeur ne correspond pas - - # Décode le sujet de l'e-mail - subject, encoding = decode_header(msg["Subject"])[0] - if isinstance(subject, bytes): - try: - subject = subject.decode(encoding if encoding else 'utf-8') - except (LookupError, UnicodeDecodeError): - subject = subject.decode('utf-8', errors='replace') # Remplace les erreurs de décodage - - # Afficher les informations de l'e-mail - print(f"From: {from_}") - print(f"Subject: {subject}") - print(f"Date: {msg.get('Date')}") - - # Afficher le corps du message - if msg.is_multipart(): - for part in msg.walk(): - content_type = part.get_content_type() - content_disposition = str(part.get("Content-Disposition")) - - if "attachment" not in content_disposition: - payload = part.get_payload(decode=True) - if payload: - try: - body = payload.decode() - except (LookupError, UnicodeDecodeError): - body = payload.decode('utf-8', errors='replace') - print(f"Body: {body}") - else: - payload = msg.get_payload(decode=True) - if payload: - try: - body = payload.decode() - except (LookupError, UnicodeDecodeError): - body = payload.decode('utf-8', errors='replace') - print(f"Body: {body}") - - print("\n" + "=" * 50 + "\n") - - -# Utilisation -username = "dbmx76@gmail.com" -password = "kghz sjzk sumo kbhg" -imap_url = "imap.gmail.com" - - -mail = connect_to_email(username, password, imap_url) -extract_job_info(mail, limit=50) -# save_to_file(job_infos) diff --git a/utils/cdi_fetcher.py b/utils/cdi_fetcher.py index 25f7b08..fc8d1bd 100644 --- a/utils/cdi_fetcher.py +++ b/utils/cdi_fetcher.py @@ -2,10 +2,26 @@ import requests -async def fetch_api_fulltime(): +async def fetch_api_fulltime(bot): + # On récupère le Cog QueryCog depuis l'instance du bot + query_cog = bot.get_cog('QueryCog') + + # Vérifier si le Cog est bien chargé + if query_cog is None: + print("Le Cog QueryCog n'est pas chargé.") + return [], "Le Cog QueryCog n'est pas chargé" + + # Obtenir la valeur de query_fulltime à partir du Cog + query_fulltime = query_cog.get_query_fulltime() + + # Vérifier si une query a été définie + if query_fulltime is None: + print("Aucune query n'a été définie.") + return [], "Aucune query n'a été définie" + url = "https://jsearch.p.rapidapi.com/search" - querystring = {"query":"full stack developer in France","page":"1","num_pages":"10","date_posted":"today","employment_types":"FULLTIME","radius":"200"} + querystring = {"query":query_fulltime,"page":"1","num_pages":"10","date_posted":"today","employment_types":"FULLTIME","radius":"200"} headers = { "x-rapidapi-key": os.getenv('RAPIDAPI_KEY'), @@ -16,7 +32,7 @@ async def fetch_api_fulltime(): response = requests.get(url, headers=headers, params=querystring) response.raise_for_status() data = response.json().get('data', []) - return data if isinstance(data, list) else [] + return data if isinstance(data, list) else [], query_fulltime except requests.exceptions.RequestException as e: print(f"Error fetching JSearch jobs: {e}") - return [] + return [], query_fulltime diff --git a/utils/config_loader.py b/utils/config_loader.py index f1c7832..93f7c27 100644 --- a/utils/config_loader.py +++ b/utils/config_loader.py @@ -23,3 +23,5 @@ def load_config(): role_help = config["role_help"] channel_inter_promo = config["channel_inter_promo"] discord_token = os.getenv("TOKEN") +query_intern = os.getenv("QUERY_INTERNSHIP") +query_fulltime = os.getenv("QUERY_FULLTIME") diff --git a/utils/intern_fetcher.py b/utils/intern_fetcher.py index 6b77eb3..63836c2 100644 --- a/utils/intern_fetcher.py +++ b/utils/intern_fetcher.py @@ -2,10 +2,26 @@ import requests -async def fetch_api_intern(): +async def fetch_api_intern(bot): + # On récupère le Cog QueryCog depuis l'instance du bot + query_cog = bot.get_cog('QueryCog') + + # Vérifier si le Cog est bien chargé + if query_cog is None: + print("Le Cog QueryCog n'est pas chargé.") + return [], "Le Cog QueryCog n'est pas chargé" + + # Obtenir la valeur de query_intern à partir du Cog + query_intern = query_cog.get_query_intern() + + # Vérifier si une query a été définie + if query_intern is None: + print("Aucune query n'a été définie.") + return [], "Aucune query n'a été définie" + url = "https://jsearch.p.rapidapi.com/search" - querystring = {"query":"full stack developer in France","page":"1","num_pages":"10","date_posted":"today","employment_types":"INTERN","radius":"200"} + querystring = {"query":query_intern,"page":"1","num_pages":"10","date_posted":"today","employment_types":"INTERN","radius":"200"} headers = { "x-rapidapi-key": os.getenv('RAPIDAPI_KEY'), @@ -16,7 +32,7 @@ async def fetch_api_intern(): response = requests.get(url, headers=headers, params=querystring) response.raise_for_status() data = response.json().get('data', []) - return data if isinstance(data, list) else [] + return data if isinstance(data, list) else [], query_intern except requests.exceptions.RequestException as e: print(f"Error fetching JSearch jobs: {e}") - return [] + return [], query_intern