diff --git a/scripts/load-docs.py b/scripts/load-docs.py index 7ba2768..0cc1dfc 100644 --- a/scripts/load-docs.py +++ b/scripts/load-docs.py @@ -1,19 +1,28 @@ """Load docs script.""" import locale +from datetime import datetime +from io import StringIO from itertools import groupby from pathlib import Path from typing import List import click +import requests +from dateutil.relativedelta import relativedelta from pydantic.tools import parse_obj_as from ruamel.yaml import YAML +from ruamel.yaml.main import add_constructor from app import crud from app.core.aws import get_meals +from app.core.config import settings from app.deps.database import manual_db from app.schemas.meal import Meal +ORIGINAL_MKDOCS_URL = ( + "https://raw.githubusercontent.com/team-ittade/peue/master/mkdocs.yml" +) MD_DIR = Path(__file__).parent.with_name("docs") MKDOCS_YML_PATH = Path(__file__).parent.parent / "mkdocs.yml" locale.setlocale(locale.LC_ALL, "es_ES.utf8") @@ -23,7 +32,8 @@ @click.command() @click.argument("source", type=click.Choice(["aws", "db"])) -def load_docs(source: str): +@click.option("--extra-week", is_flag=True) +def load_docs(source: str, extra_week: bool): """Load the docs from AWS or the database.""" if source == "aws": meals = get_meals() @@ -32,15 +42,59 @@ def load_docs(source: str): meals = parse_obj_as(List[Meal], crud.meal.get_multi(db)) weeks = [] + week = 0 + + meals = filter_meals(meals) + for week, weekly_meals in groupby(meals, lambda x: x.id.isocalendar()[1]): weeks.append(week) weekly_meals = list(weekly_meals) create_md(week, weekly_meals) + if extra_week and week: + current_week = datetime.now().isocalendar().week + next_week = current_week + 1 if current_week != 52 else 1 + + weeks.append(next_week) + create_md(next_week, [], override=False) + + recreate_md_index(weeks) rebuild_mkdocs_yml(weeks) -def create_md(week: int, weekly_meals: List[Meal]): +def filter_meals(meals: List[Meal]) -> List[Meal]: + ts_1 = datetime.now().date() + ts_0 = ts_1 - relativedelta(months=1) + + week_0 = ts_0.isocalendar().week + week_1 = ts_1.isocalendar().week + + week_0 = week_0 + 1 if week_0 != 52 else 1 + + if week_0 > week_1: + valid_weeks = tuple(range(week_0, 53)) + tuple(range(1, week_1 + 1)) + else: + valid_weeks = tuple(range(week_0, week_1 + 1)) + + return [x for x in meals if x.id.isocalendar().week in valid_weeks] + + +def get_weekdays(): + return [datetime(2001, 1, i).strftime("%A") for i in range(1, 8)] + + +def get_default_md_text(): + output = "# Semana XXXX-XX-XX\n" + + weekdays = settings.LOCALE_WEEKDAY_NAMES or get_weekdays() + + for weekday in weekdays: + output += f"\n## {weekday.title()}\n" + + return output + + +def create_md(week: int, weekly_meals: List[Meal], override=True): """Creates the markdown file.""" MD_DIR.mkdir(exist_ok=True) md_filepath = MD_DIR / f"{week}.md" @@ -57,13 +111,56 @@ def create_md(week: int, weekly_meals: List[Meal]): content += f"- {meal.lunch2}\n" content += f"\n- {meal.dinner}\n" + if not content: + content = get_default_md_text() + + if md_filepath.exists() and not override: + data = md_filepath.read_text("utf8") + if content != data: + click.secho( + f"Skipping write of {md_filepath} (override=False)", fg="bright_yellow" + ) + return + md_filepath.write_text(content, "utf8") +def recreate_md_index(weeks: List[int]): + index_path = MD_DIR / "index.md" + output = "# Meal Planner - Planificador de comidas\n\n" + for week in weeks: + output += f"- [Semana {week}]({week}.md)\n" + + output = output.strip() + "\n" + index_path.write_text(output, "utf8") + + def rebuild_mkdocs_yml(weeks: List[int]): """Rebuilds the mkdocs.yml file.""" - with MKDOCS_YML_PATH.open("rt", encoding="utf8") as fh: - yml_content = yml.load(fh) + try: + with MKDOCS_YML_PATH.open("rt", encoding="utf8") as fh: + yml_content = yml.load(fh) + except FileNotFoundError: + click.secho("Warning: mkdocs.yml not found, downloading it", fg="bright_yellow") + response = requests.get(ORIGINAL_MKDOCS_URL).text + response = "\n".join([x for x in response.splitlines() if "emoji." not in x]) + yml_content = yml.load(StringIO(response)) + yml_content["site_name"] = "Meal Planner" + yml_content["theme"]["palette"]["primary"] = "teal" + + del yml_content["theme"]["logo"] + del yml_content["theme"]["favicon"] + del yml_content["extra_css"] + del yml_content["extra_javascript"] + del yml_content["repo_name"] + del yml_content["repo_url"] + del yml_content["plugins"] + + extensions = yml_content["markdown_extensions"] + yml_content["markdown_extensions"] = [ + x for x in extensions if "include" not in str(x) + ] + yml_content["nav"] = [{"Índice": "index.md"}] yml_content["nav"] += [{f"Semana {x}": f"{x}.md"} for x in weeks] diff --git a/scripts/manage.py b/scripts/manage.py index 84dfa4a..b753d75 100644 --- a/scripts/manage.py +++ b/scripts/manage.py @@ -20,7 +20,7 @@ PATTERN = r"## (?P[\wáéó]+)\n(?P[\[\]\-\/()\wáéó\n ]+)\n(?P[\[\]\-\/()\wáéó\n ]+)\n" MD_DIR = Path(__file__).parent.parent / "docs" -MD_FILES = [x.stem for x in MD_DIR.iterdir() if x.suffix == ".md"] +MD_FILES = [x.stem for x in MD_DIR.iterdir() if x.suffix == ".md" and x.stem.isdigit()] YML_FILES = [x.stem for x in MD_DIR.iterdir() if x.suffix == ".yml"] JSON_FILES = [x.stem for x in MD_DIR.iterdir() if x.suffix == ".json"] @@ -95,8 +95,16 @@ def convert_md_to_yml(date: str): yaml_path.write_text(re.sub("(- date:)", r"\n\1", unparsed_data), encoding="utf8") -@cli.command("yml-json") +@cli.command("confirm") @click.argument("date", metavar="DATE", type=click.Choice(YML_FILES)) +@click.option("--dry-run", "-n", is_flag=True, help="Dry run mode") +@click.argument("API_URL", envvar="MEAL_PLANNER_API_URL", required=False) +def upload_yml(date: str, api_url: str, dry_run: bool): + convert_yml_json(date) + if not dry_run: + upload_json(date, api_url) + + def convert_yml_json(date: str): filepath = MD_DIR / f"{date}.yml" with filepath.open("rt", encoding="utf8") as fh: @@ -113,16 +121,13 @@ def convert_yml_json(date: str): return click.confirm( - "YML file exists and will be modified. Continue?", abort=True, default=True + "JSON file exists and will be modified. Continue?", abort=True, default=True ) with json_path.open("wt", encoding="utf8") as fh: json.dump(jsonable_encoder(parsed_data), fh, indent=2, ensure_ascii=False) -@cli.command("upload-json") -@click.argument("date", metavar="DATE", type=click.Choice(JSON_FILES)) -@click.argument("API_URL", envvar="MEAL_PLANNER_API_URL") def upload_json(date: str, api_url: str): filepath = MD_DIR / f"{date}.json" headers = {"x-token": settings.API_TOKEN, "user-agent": "mealer"}