import os from sys import stdin, stdout, argv from uuid import uuid4 from json import dumps, load import psycopg from psycopg import Cursor import pandas as pd from app.data.QueryManager import QueryManager, display_mapper from app.parse_recipe import parse_recipe try: from db_credentials import HOST, PASSWORD host = f'host={HOST}' password = f'password={PASSWORD}' except: host = '' password = '' user = os.getenv('USER') conn = psycopg.connect(f"{host} dbname=grocery user={user} {password}") cur: Cursor = conn.cursor() query_manager = QueryManager(cur, display_mapper) with open(argv[1], 'rb') as f: units = { x['name']: x for x in load(f) } # { # "id": "7cb5a83d-268a-4898-b24e-08b4753039a5", # "userId": "d0f22cce-fa1c-420e-98ae-d85831c725b1", # "groupId": "c6229a83-ce82-4be1-9683-ff14f83025c9", # "name": "Another", # "slug": "another", # "image": null, # "recipeYield": null, # "totalTime": null, # "prepTime": null, # "cookTime": null, # "performTime": null, # "description": "", # "recipeCategory": [], # "tags": [], # "tools": [], # "rating": null, # "orgURL": null, # "dateAdded": "2024-04-14", # "dateUpdated": "2024-04-14T18:49:34.284815", # "createdAt": "2024-04-14T18:49:34.293412", # "updateAt": "2024-04-14T18:49:34.293418", # "lastMade": null, # "recipeIngredient": [ # { # "quantity": 1.0, # "unit": null, # "food": null, # "note": "1 Cup Flour", # "isFood": false, # "disableAmount": true, # "display": "1 Cup Flour", # "title": null, # "originalText": null, # "referenceId": "2e4403e7-fbfb-42b6-b38b-adf38f09bf78" # } # ], # "recipeInstructions": [ # { # "id": "f8c85a36-1044-45e7-b22b-e37764d892a9", # "title": "", # "text": "Recipe steps as well as other fields in the recipe page support markdown syntax.\n\n**Add a link**\n\n[My Link](https://demo.mealie.io)\n\n", # "ingredientReferences": [] # } # ], # "nutrition": { # "calories": null, # "fatContent": null, # "proteinContent": null, # "carbohydrateContent": null, # "fiberContent": null, # "sodiumContent": null, # "sugarContent": null # }, # "settings": { # "public": true, # "showNutrition": true, # "showAssets": true, # "landscapeView": false, # "disableComments": true, # "disableAmount": true, # "locked": false # }, # "assets": [], # "notes": [], # "extras": {}, # "comments": [] # } cur.execute("BEGIN;") with open('units.sql') as f: to_exec = '' quote = False conn.add_notice_handler(lambda x: print(f"[{x.severity}] {x.message_primary}")) for line in filter(lambda x: x.strip() not in ('BEGIN;','ROLLBACK;'), f): if line.startswith("""$$"""): quote = True if not quote else False to_exec += line if not line.strip().endswith(';'): continue if quote: continue cur.execute(to_exec) try: data = pd.DataFrame(cur.fetchall(), columns=[ x.name for x in cur.description ]) if not data.empty: print() print(cur._last_query) print(data.to_string(index=False)) except psycopg.ProgrammingError: pass to_exec = '' parsed = parse_recipe(stdin, query_manager) cur.execute('ROLLBACK') def unit_mapper(unit): if 'Cup' in unit: return 'cup' return unit.replace(' (metric)', '').replace(' (US)', '') mealie = { 'recipeYield': parsed['feeds'], 'recipeInstructions': [{ "id": str(uuid4()), "title": "", "text": line, "ingredientReferences": [], } for line in parsed['instructions'].splitlines()], 'recipeIngredient': [{ "quantity": quantity, "unit": units[unit_mapper(unit)], "food": None, "note": product, "isFood": False, "disableAmount": False, "display": product, "title": None, "originalText": o, "referenceId": str(uuid4()) } for product, quantity, unit, o in map( lambda x: (*x, ' '.join([*x[1:], x[0]])), parsed['ingredients'] )] } stdout.write(dumps(mealie)) cur.close() conn.close()