Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fonctionnalité : ajoute une commande pour afficher un commentaire spécifique via son identifiant #155

Merged
merged 4 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion geotribu_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from geotribu_cli.subcommands import (
parser_comments_broadcast,
parser_comments_latest,
parser_comments_read,
parser_images_optimizer,
parser_latest_content,
parser_new_article,
Expand Down Expand Up @@ -255,7 +256,18 @@ def main(args: list[str] = None):
title="Commentaires", dest="cmd_comments"
)

# Publier le dernier commentaire
# Consulter un commentaire
subcmd_comments_open = comments_subparsers.add_parser(
"open",
aliases=["lire", "open", "ouvrir"],
help="Afficher un commentaire en particulier.",
formatter_class=main_parser.formatter_class,
prog="comments-read",
)
add_common_arguments(subcmd_comments_open)
parser_comments_read(subcmd_comments_open)

# Diffuser un commentaire
subcmd_comments_broadcast = comments_subparsers.add_parser(
"broadcast",
aliases=["diffuser", "publier"],
Expand Down
1 change: 1 addition & 0 deletions geotribu_cli/comments/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
# submodules
from .comments_broadcast import parser_comments_broadcast # noqa: F401
from .comments_latest import parser_comments_latest # noqa: F401
from .comments_open import parser_comments_read # noqa: F401
from .mdl_comment import Comment # noqa: F401
14 changes: 12 additions & 2 deletions geotribu_cli/comments/comments_latest.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def get_latest_comments(
"author_asc", "author_desc", "created_asc", "created_desc"
] = "created_asc",
expiration_rotating_hours: int = 1,
attempt: int = 1,
) -> list[Comment]:
"""Download and parse latest comments published.

Expand All @@ -115,8 +116,17 @@ def get_latest_comments(
content_type="application/json",
)

with comments_file.open(mode="r", encoding="UTF-8") as f:
comments = json.loads(f.read())
try:
with comments_file.open(mode="r", encoding="UTF-8") as f:
comments = json.loads(f.read())
except json.decoder.JSONDecodeError as err:
logger.error(f"Impossible de lire le fichier des commentaires. Trace {err}")
if attempt < 2:
logger.info("Deuxième essai en forçant le téléchargement du fichier.")
return get_latest_comments(
number=number, sort_by=sort_by, expiration_rotating_hours=0, attempt=2
)
raise err

li_comments = [Comment(**c) for c in comments]

Expand Down
259 changes: 259 additions & 0 deletions geotribu_cli/comments/comments_open.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
#! python3 # noqa: E265

# ############################################################################
# ########## IMPORTS #############
# ################################

# standard library
import argparse
import json
import logging
import sys
from os import getenv
from typing import Optional

# 3rd party
from rich import print

# package
from geotribu_cli.comments.comments_latest import (
format_output_result,
get_latest_comments,
)
from geotribu_cli.comments.mdl_comment import Comment
from geotribu_cli.constants import GeotribuDefaults

# ############################################################################
# ########## GLOBALS #############
# ################################

logger = logging.getLogger(__name__)
defaults_settings = GeotribuDefaults()

# ############################################################################
# ########## FUNCTIONS ###########
# ################################


def find_comment_by_id(comment_id: int) -> Optional[Comment]:
"""Trouve un commentaire parmi les derniers téléchargés d'après son id.

Args:
comment_id: id du commentaire à trouver.

Returns:
le commentaire trouvé ou None s'il n'est pas présent dans le fichier des
derniers commentaires.
"""
comments_file = defaults_settings.geotribu_working_folder.joinpath(
"comments/latest.json"
)
with comments_file.open(mode="r", encoding="UTF-8") as f:
comments = json.loads(f.read())

li_comments = [Comment(**c) for c in comments]

for comment in li_comments:
if comment.id == comment_id:
logger.info(f"Commentaire {comment_id} trouvé.")
return comment

logger.info(
f"Le commentaire {comment_id} n'a pas été trouvé parmi les {len(li_comments)} "
"commentaires récupérés."
)
return None


# ############################################################################
# ########## CLI #################
# ################################


def parser_comments_read(
subparser: argparse.ArgumentParser,
) -> argparse.ArgumentParser:
"""Set the argument parser for subcommand.

Args:
subparser (argparse.ArgumentParser): parser to set up

Returns:
argparse.ArgumentParser: parser ready to use
"""

subparser.add_argument(
"-c",
"--comment-id",
default=None,
dest="comment_id",
help="Identifiant du commentaire à afficher. Doit faire partie des 100 derniers. "
"Par défaut, on publie le dernier commentaire.",
required=False,
type=int,
)

subparser.add_argument(
"-o",
"--format-output",
choices=[
"json",
"table",
],
default=getenv("GEOTRIBU_RESULTATS_FORMAT", "table"),
help="Format de sortie.",
dest="format_output",
metavar="GEOTRIBU_RESULTATS_FORMAT",
)

subparser.add_argument(
"-p",
"--page-size",
default=getenv("GEOTRIBU_COMMENTS_API_PAGE_SIZE", 20),
dest="page_size",
help="Nombre de commentaires par requêtes. Plus le commentaire est récent, plus "
"c'est performant d'utiliser une petite page. À l'inverse, si on cherche un "
"vieux commentaire, utiliser une grande page. Valeur par défaut : 20.",
metavar="GEOTRIBU_COMMENTS_API_PAGE_SIZE",
required=False,
type=int,
)

subparser.add_argument(
"-w",
"--with",
choices=[
"app",
"shell",
],
default=getenv("GEOTRIBU_OPEN_WITH", "shell"),
dest="open_with",
help="Avec quoi ouvrir le commentaire : dans le terminal (shell) ou dans le "
"navigateur (sous l'article). Valeur par défault : 'shell'.",
metavar="GEOTRIBU_OPEN_WITH",
)

subparser.add_argument(
"-x",
"--expiration-rotating-hours",
default=12,
dest="expiration_rotating_hours",
help="Nombre d'heures à partir duquel considérer le fichier local comme périmé.",
type=int,
)

subparser.set_defaults(func=run)

return subparser


# ############################################################################
# ########## MAIN ################
# ################################


def run(args: argparse.Namespace):
"""Run the sub command logic.

Open result of a previous command.

Args:
args (argparse.Namespace): arguments passed to the subcommand
"""
logger.debug(f"Running {args.command} with {args}")
comment_obj = {}
comment_found = False

try:
# on récupère d'abord le premier commentaire soit pour le retourner, soit pour
# limiter le nombre de requêtes
latest_comment = get_latest_comments(
number=1,
sort_by="created_desc",
expiration_rotating_hours=args.expiration_rotating_hours,
)

except Exception as err:
logger.error(
f"Une erreur a empêché la récupération du dernier commentaire. Trace: {err}"
)
sys.exit(1)

# si c'est le dernier commentaire qui a été demandé ou si rien n'a été précisé,
# alors on le retourne sans plus attendre
if args.comment_id is None or args.comment_id == latest_comment[0].id:
print(
format_output_result(
results=latest_comment, format_type=args.format_output, count=1
)
)
sys.exit(0)

try:
# on récupère d'abord le premier commentaire soit pour le retourner, soit pour
# limiter le nombre de requêtes
latest_comment = get_latest_comments(
number=1,
sort_by="created_desc",
expiration_rotating_hours=args.expiration_rotating_hours,
)[0]

if args.comment_id is None or 0:
comment_found = True
comment_obj = latest_comment

api_request_page_size = args.page_size
# doit être à 0 si le com' n'est pas trouvé dans le fichier local pour forcer le téléchargement incrémental
local_expiration_delay_hours = args.expiration_rotating_hours

while all(
[comment_found is False, api_request_page_size <= int(latest_comment.id)]
):
published_comments = get_latest_comments(
number=api_request_page_size,
sort_by="created_desc",
expiration_rotating_hours=local_expiration_delay_hours,
)

if not len(published_comments):
print(":person_shrugging: Aucun commentaire trouvé")
sys.exit(0)

comment_obj = find_comment_by_id(comment_id=args.comment_id)

if isinstance(comment_obj, Comment):
comment_found = True
break
else:
logger.debug(
f"Le commentaire {args.comment_id} n'a pas été trouvé parmi les "
f"{api_request_page_size} derniers commentaires. Nouvelle requête "
f"pour chercher parmi les {api_request_page_size*2} derniers commentaires..."
)
api_request_page_size = api_request_page_size * 2
local_expiration_delay_hours = 0
except Exception as err:
logger.error(
f"Une erreur a empêché la récupération des commentaires. Trace: {err}"
)
sys.exit(1)

# si le commentaire n'a pas été trouvé
if not isinstance(comment_obj, Comment):
print(
f":person_shrugging: Le commentaire {args.comment_id} n'a pu être trouvé. "
"Est-il publié et validé ?"
)
sys.exit(0)

print(
format_output_result(
results=[comment_obj], format_type=args.format_output, count=1
)
)
sys.exit(0)


# -- Stand alone execution
if __name__ == "__main__":
pass
9 changes: 4 additions & 5 deletions geotribu_cli/subcommands/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#! python3 # noqa: E265
#! python3 # noqa: E265 F401

# submodules
from geotribu_cli.comments import ( # noqa: F401
parser_comments_broadcast,
parser_comments_latest,
)
from geotribu_cli.comments import parser_comments_broadcast # noqa: F401
from geotribu_cli.comments import parser_comments_latest # noqa: F401
from geotribu_cli.comments import parser_comments_read # noqa: F401
from geotribu_cli.content.new_article import parser_new_article # noqa: F401
from geotribu_cli.images.images_optimizer import parser_images_optimizer # noqa: F401
from geotribu_cli.rss.rss_reader import parser_latest_content # noqa: F401
Expand Down
10 changes: 5 additions & 5 deletions geotribu_cli/utils/file_downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ def download_remote_file_to_local(
expiration_rotating_hours=expiration_rotating_hours,
):
logger.info(
f"Local search index ({local_file_path}) is outdated: "
f"updated more than {expiration_rotating_hours} hour(s) ago. "
"Let's remove and download it again from remote."
f"Le fichier local ({local_file_path}) est périmé: "
f"il a été mis à jour il y a plus de {expiration_rotating_hours} heures."
"Il a besoin d'être de nouveau téléchargé."
)
local_file_path.unlink(missing_ok=True)
else:
logger.info(
f"Local search index ({local_file_path}) is up to date. "
"No download needed.",
f"Le fichier local ({local_file_path}) est à jour par rapport au délai "
f"d'expiration spécifié ({expiration_rotating_hours}). Pas besoin de le retélécharger.",
)
return local_file_path

Expand Down