Skip to content

Commit

Permalink
Merge pull request #1 from tarto-dev/improve-doc
Browse files Browse the repository at this point in the history
Improve global code quality & documentation
  • Loading branch information
tarto-dev authored Feb 15, 2024
2 parents 8c80519 + d349563 commit edab1ed
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 51 deletions.
46 changes: 46 additions & 0 deletions api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,77 @@

class EOLApi:
def __init__(self):
"""
Initialize a new EOLApi instance.
"""
self.session = requests.Session()
self.session.headers.update({"accept": "application/json"})

def __enter__(self):
"""
Support for with statement.
"""
return self

def __exit__(self, exc_type, exc_val, exc_traceback):
"""
Close the session when the with statement is done.
"""
self.close()

def close(self):
"""
Close the current session.
"""
self.session.close()

def _get_results(self, endpoint) -> dict:
"""
Send a GET request to the specified endpoint and return the JSON response.
Args:
endpoint (str): The API endpoint to send the GET request to.
Returns:
dict: The JSON response from the API.
"""
res = self.session.get(endpoint)
res.raise_for_status()
return res.json()

def get_product_details(self, product: str) -> dict:
"""
Get the details of a specific product.
Args:
product (str): The name of the product.
Returns:
dict: The details of the product.
"""
endpoint = f"{API_URL}/{product}.json"
return self._get_results(endpoint)

def get_single_cycle_details(self, product: str, cycle: str) -> dict:
"""
Get the details of a specific cycle of a product.
Args:
product (str): The name of the product.
cycle (str): The name of the cycle.
Returns:
dict: The details of the cycle.
"""
endpoint = f"{API_URL}/{product}/{cycle}.json"
return self._get_results(endpoint)

def get_all_products(self):
"""
Get the details of all products.
Returns:
dict: The details of all products.
"""
endpoint = f"{API_URL}/all.json"
return self._get_results(endpoint)
128 changes: 86 additions & 42 deletions bot.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Importing necessary modules
from disnake.ext import commands
from disnake import Embed, ApplicationCommandInteraction
from disnake.ext.commands import InteractionBot # Import InteractionBot

# Importing functions and constants from other modules
from main import (
Expand All @@ -11,36 +12,59 @@
)
from configs import BOT_TOKEN

# Creating a commands.Bot() instance and initializing products from API
bot = commands.Bot()
bot = InteractionBot()
products = get_all_products_from_api()


# Autocomplete function for product names
async def autocomp_products(inter: ApplicationCommandInteraction, input: str):
return [lang for lang in products if input.lower() in lang]
"""
Autocomplete function for product names.
Args:
inter (ApplicationCommandInteraction): The interaction that triggered the autocomplete.
input (str): The current input of the user.
Returns:
list: A list of product names that contain the user's input.
"""
# Lowercase the input to make the search case-insensitive
input_lower = input.lower()
return [product for product in products if input_lower in product.lower()]


# Event handler for when the bot is ready
@bot.event
async def on_ready():
"""
Event handler for when the bot is ready.
Prints a message to the console.
"""
print("The bot is ready!")


# Slash command to get all available products
@bot.slash_command(description="Gets all available products")
async def get_products(inter):
"""
Slash command to get all available products.
Sends an embed with a list of all available products.
Args:
inter (ApplicationCommandInteraction): The interaction that triggered the command.
"""
embedList = []

results_per_embed = 35
max_pages = 1 + (len(products) // results_per_embed)

# Creating paginated Embed messages for product list
for product in batch(products, results_per_embed):
for product_batch in batch(products, results_per_embed):
embed = Embed(
title=f"Available products [{len(embedList) + 1 } out of {max_pages}]"
)
embed.add_field(name="", value=",".join(product))
# Provide a name for the field
embed.add_field(name="Products", value=",".join(product_batch))
embedList.append(embed)

await inter.channel.send(embeds=embedList)
Expand All @@ -59,50 +83,55 @@ async def product_details(
default=True, description="Include all minors versions ?"
),
):
embedList = []
"""
Slash command to get details of all cycles of a given product.
Sends an embed with the details of all cycles of a given product.
Args:
inter (ApplicationCommandInteraction): The interaction that triggered the command.
product (str): The name of the product.
majors_only (bool): Whether to include all minor versions.
Returns:
None
"""
product_details_cycles = get_product_details_from_api(
product=product, majors_only=majors_only
)

# Displaying only the first three cycles if there are more
# Limiting the number of displayed cycles to the first five
max_size = 5
if len(product_details_cycles) >= max_size:
product_details_cycles = product_details_cycles[:max_size]
product_details_cycles = product_details_cycles[:max_size]

# Iterating over each product detail cycle
for product_details in product_details_cycles:
embed = Embed(title=f"Product {product} - {product_details['cycle']}")
first_separator = False
second_separator = False

# Adding fields for latest build and release date
# Adding fields for latest build and release date if they exist
if "latest" in product_details:
embed.add_field(name="Latest build", value=product_details["latest"])
first_separator = True

if "latestReleaseDate" in product_details:
embed.add_field(
name="Latest build release", value=product_details["latestReleaseDate"]
)
first_separator = True

# Adding separator if there are previous fields
if first_separator:
# Adding a separator if there are previous fields
if "latest" in product_details or "latestReleaseDate" in product_details:
embed.add_field(name="\u200B", value="\u200B", inline=False)

# Adding fields for end of support and end of life
# Adding fields for end of support and end of life if they exist
if "support" in product_details:
embed.add_field(name="End of support", value=product_details["support"])
second_separator = True

if "eol" in product_details:
embed.add_field(name="End of life", value=product_details["eol"])
second_separator = True

# Adding separator if there are previous fields
if second_separator:
# Adding a separator if there are previous fields
if "support" in product_details or "eol" in product_details:
embed.add_field(name="\u200B", value="\u200B", inline=False)

# Adding fields for LTS status and discontinuation status
# Adding fields for LTS status and discontinuation status if they exist
if "lts" in product_details:
embed.add_field(
name="Is long time support ?",
Expand All @@ -115,61 +144,70 @@ async def product_details(
value="yes" if product_details["discontinued"] else "no",
)

embedList.append(embed)

await inter.channel.send(embeds=embedList)
# Sending the embed
await inter.channel.send(embed=embed)


# Slash command to get details of a single cycle for a given product
@bot.slash_command(description="Gets details of a single cycle")
@bot.slash_command(description="Gets details of a single cycle for a given product.")
async def product_cycle(
inter,
product: str = commands.Param(
description="Product name (autocompleted)",
min_length=3,
autocomplete=autocomp_products,
),
cycle: str = commands.Param(max_length=10),
cycle: str = commands.Param(max_length=10, description="Cycle name"),
):
"""
Slash command to get details of a single cycle for a given product.
Sends an embed with the details of a single cycle for a given product.
Args:
inter (ApplicationCommandInteraction): The interaction that triggered the command.
product (str): The name of the product.
cycle (str): The name of the cycle.
Returns:
None
"""
# Retrieving details of a single cycle from API
product_details_cycles = get_single_cycle_details_from_api(
product=product, cycle=cycle
)

# Creating an Embed message with the product and cycle as the title
embed = Embed(title=f"Product {product} - {cycle}")
first_separator = False
second_separator = False

# Adding fields for latest build and release date
# Adding fields for latest build and release date if they exist
if "latest" in product_details_cycles:
embed.add_field(name="Latest build", value=product_details_cycles["latest"])
first_separator = True

if "latestReleaseDate" in product_details_cycles:
embed.add_field(
name="Latest build release",
value=product_details_cycles["latestReleaseDate"],
)
first_separator = True

# Adding separator if there are previous fields
if first_separator:
# Adding a separator if there are previous fields
if (
"latest" in product_details_cycles
or "latestReleaseDate" in product_details_cycles
):
embed.add_field(name="\u200B", value="\u200B", inline=False)

# Adding fields for end of support and end of life
# Adding fields for end of support and end of life if they exist
if "support" in product_details_cycles:
embed.add_field(name="End of support", value=product_details_cycles["support"])
second_separator = True

if "eol" in product_details_cycles:
embed.add_field(name="End of life", value=product_details_cycles["eol"])
second_separator = True

# Adding separator if there are previous fields
if second_separator:
# Adding a separator if there are previous fields
if "support" in product_details_cycles or "eol" in product_details_cycles:
embed.add_field(name="\u200B", value="\u200B", inline=False)

# Adding fields for LTS status and discontinuation status
# Adding fields for LTS status and discontinuation status if they exist
if "lts" in product_details_cycles:
embed.add_field(
name="Is long time support ?",
Expand All @@ -181,9 +219,15 @@ async def product_cycle(
name="Is discontinued ?",
value="yes" if product_details_cycles["discontinued"] else "no",
)

# Sending the Embed message
await inter.channel.send(embeds=embed)
await inter.channel.send(embed=embed)


# Running the bot with the provided token
bot.run(BOT_TOKEN)
if __name__ == "__main__":
"""
Main execution of the bot.
This block is executed when the script is run directly, not when it is imported as a module.
"""
bot.run(BOT_TOKEN)
Loading

0 comments on commit edab1ed

Please sign in to comment.