import click from markdown import markdown from jinja2 import Environment, FileSystemLoader from grocy.conf import Configuration from grocy.recipe import Recipe from grocy.table import Table from grocy.entity import Entity from grocy.stock import Stock import yaml from sys import exit from os import path import logging APP_NAME = 'grocy-cli' SAMPLE_CONFIG_FILE = 'sample.config.yml' TMP_DIR = '/tmp/grocy' CONFIG_FILE = 'config.yml' CONFIG_DIR = click.get_app_dir(APP_NAME) PROJ_DIR = path.join(path.dirname(path.realpath(__file__))) TEMPLATE_LOADER = Environment(loader=FileSystemLoader('templates'), trim_blocks=True, lstrip_blocks=True) def __validate_token(cfg): # Validate token if hasattr(cfg, 'token') or cfg['token'] is None: click.echo('No token was found. Please add your token to the config file', err=True) #logger.error('No token was found. Please add your token') exit(1) @click.group() def main(): cfg = Configuration() if not cfg.exists: no_config_msg = 'A config file was not found. A sample configuration file' no_config_msg += ' will be created under {}. Is that Ok?'.format(cfg.CONFIG_DIR) create_config_app_dir = click.confirm(no_config_msg) user_cfg_options = {} if create_config_app_dir: user_cfg_options['logger_level'] = click.prompt('Enter logger level', default='DEBUG') user_cfg_options['logger_file_location'] = click.prompt('Enter location for logger', default=path.expanduser('~/.config/grocy/log')) user_cfg_options['api'] = click.prompt('Enter the grocy api url', default='https://demo-en.grocy.info/api') user_cfg_options['token'] = click.prompt('Enter the grocy token ', default='') user_cfg_options['col_format'] = click.prompt('Enter the col position for rendering tables', default='col') user_cfg_options['table_format'] = click.prompt('Enter the table format', default='simple') cfg.create(user_cfg_options) else: exit(0) else: cfg.load() logging.basicConfig(level=cfg.logger_level, filename=cfg.logger_file_location) @main.command() @click.pass_context def stock(ctx): logger = logging.getLogger('cli.stock') if ctx.invoked_subcommand is None: try: entity = Stock() stocks = entity.get() table = Table(stocks=stocks) click.echo(table.stock) except Exception as e: logger.error(e) raise e @main.command() def shopping(): logger = logging.getLogger('cli.shopping') try: entity = Entity(name='shopping_list') shopping_list = entity.get() table = Table(shopping_list=shopping_list) click.echo(table.shopping_list) except Exception as e: logger.error(e) raise e @main.group() def ingredient(ctx): pass @ingredient.command('add') @click.option('-r', '--recipe_id') def add(ctx, recipe_id): logger = logging.getLogger('cli.ingredient.add') try: loaded_template = TEMPLATE_LOADER.get_template('ingredient_add.yml') if recipe_id: entity = Entity(name='recipes') recipe = entity.get(id=recipe_id) new_ingredient = click.edit(loaded_template.render(recipe)) parsed_new_ingredient = yaml.safe_load(new_ingredient) else: new_ingredient = click.edit(loaded_template.render()) parsed_new_ingredient = yaml.safe_load(new_ingredient) if parsed_new_ingredient['recipe_id']: raise Exception('Recipe id is not defined') if new_ingredient: entity = Entity(name='ingredients', **parsed_new_ingredient) entity.create() except Exception as e: logger.error(e) @main.group() @click.pass_context def recipe(ctx): pass @recipe.command('ls') def ls(): logger = logging.getLogger('cli.recipe') try: entity = Entity(name='recipes') recipes = entity.get() recipe = Recipe() recipes_reqs = recipe.get_requirements() table = Table(recipes=recipes, recipes_reqs=recipes_reqs) click.echo(table.recipe) except Exception as e: logger.error(e) raise e @recipe.command('edit') @click.argument('recipe_id') def edit(recipe_id): logger = logging.getLogger('cli.recipe.edit') try: if recipe_id: entity = Entity(name='recipes') recipe = entity.get(id=recipe_id) loaded_template = TEMPLATE_LOADER.get_template('recipe_edit.yml') edited_recipe = click.edit(loaded_template.render(recipe)) if edited_recipe is not None: parsed_edited_recipe = yaml.safe_load(edited_recipe) parsed_edited_recipe['description'] = markdown(parsed_edited_recipe['description']) recipe.__dict__.update(parsed_edited_recipe) recipe.update() except Exception as e: logger.error(e) logger.error('Could not edit recipe {}'.format(recipe_id)) raise e @recipe.command('create') @click.pass_context def create(ctx): logger = logging.getLogger('cli.recipe.create') try: recipe = Entity(name='recipes') loaded_template = TEMPLATE_LOADER.get_template('recipe_add.yml') new_recipe = click.edit(loaded_template.render()) if new_recipe is not None: parsed_new_recipe = yaml.safe_load(new_recipe) parsed_new_recipe['description'] = markdown(parsed_new_recipe['description']) recipe.__dict__.update(parsed_new_recipe) recipe.create() except Exception as e: logger.error(e) raise e #@main.command() #@click.pass_context #def chore(ctx): # cfg = ctx.obj['cfg'] # # chore = Chore(**cfg) # chores = chore.get_list() # click.echo(chores) # #@main.command() #@click.pass_context #def task(ctx): # cfg = ctx.obj['cfg'] # # task = Task(**cfg) # tasks = task.get_list() # click.echo(tasks)