Ejemplo n.º 1
0
def hook(request, token):
    try:
        tb = get_object_or_404(TelegramBot, webhook_token=token)

        data = json.loads(request.body.decode())

        if tb.chat_id == '':
            tb.chat_id = data['message']['chat']['id']
            tb.save()

        if tb.chat_id == str(data['message']['chat']['id']):
            request.space = tb.space  # TODO this is likely a bad idea. Verify and test
            request.user = tb.created_by
            ingredient_parser = IngredientParser(request, False)
            amount, unit, food, note = ingredient_parser.parse(
                data['message']['text'])
            f = ingredient_parser.get_food(food)
            u = ingredient_parser.get_unit(unit)

            ShoppingListEntry.objects.create(food=f,
                                             unit=u,
                                             amount=amount,
                                             created_by=request.user,
                                             space=request.space)

            return JsonResponse({'data': data['message']['text']})
    except Exception:
        traceback.print_exc()

    return JsonResponse({})
Ejemplo n.º 2
0
def hook(request, token):
    try:
        tb = get_object_or_404(TelegramBot, webhook_token=token)

        data = json.loads(request.body.decode())

        if tb.chat_id == '':
            tb.chat_id = data['message']['chat']['id']
            tb.save()

        if tb.chat_id == str(data['message']['chat']['id']):
            sl = ShoppingList.objects.filter(
                Q(created_by=tb.created_by)).filter(
                    finished=False,
                    space=tb.space).order_by('-created_at').first()
            if not sl:
                sl = ShoppingList.objects.create(created_by=tb.created_by,
                                                 space=tb.space)

            request.space = tb.space  # TODO this is likely a bad idea. Verify and test
            request.user = tb.created_by
            ingredient_parser = IngredientParser(request, False)
            amount, unit, ingredient, note = ingredient_parser.parse(
                data['message']['text'])
            f = ingredient_parser.get_food(ingredient)
            u = ingredient_parser.get_unit(unit)
            sl.entries.add(
                ShoppingListEntry.objects.create(food=f, unit=u,
                                                 amount=amount))
            return JsonResponse({'data': data['message']['text']})
    except Exception:
        pass

    return JsonResponse({})
Ejemplo n.º 3
0
    def get_recipe_from_file(self, file):
        servings = 1
        ingredients = []
        directions = []
        for line in file.replace('\r', '').split('\n'):
            if not line.startswith('MMMMM') and line.strip != '':
                if 'Title:' in line:
                    title = line.replace('Title:', '').strip()
                else:
                    if 'Categories:' in line:
                        tags = line.replace('Categories:', '').strip()
                    else:
                        if 'Yield:' in line:
                            servings_text = line.replace('Yield:', '').strip()
                        else:
                            if re.match('\s{2,}([0-9])+', line):
                                ingredients.append(line.strip())
                            else:
                                directions.append(line.strip())

        try:
            servings = re.findall('([0-9])+', servings_text)[0]
        except Exception as e:
            print('failed parsing servings ', e)

        recipe = Recipe.objects.create(name=title,
                                       servings=servings,
                                       created_by=self.request.user,
                                       internal=True,
                                       space=self.request.space)

        for k in tags.split(','):
            keyword, created = Keyword.objects.get_or_create(
                name=k.strip(), space=self.request.space)
            recipe.keywords.add(keyword)

        step = Step.objects.create(
            instruction='\n'.join(directions) + '\n\n',
            space=self.request.space,
        )

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in ingredients:
            if len(ingredient.strip()) > 0:
                amount, unit, ingredient, note = ingredient_parser.parse(
                    ingredient)
                f = ingredient_parser.get_food(ingredient)
                u = ingredient_parser.get_unit(unit)
                step.ingredients.add(
                    Ingredient.objects.create(
                        food=f,
                        unit=u,
                        amount=amount,
                        note=note,
                        space=self.request.space,
                    ))
        recipe.steps.add(step)

        return recipe
Ejemplo n.º 4
0
    def get_recipe_from_file(self, file):

        ingredient_mode = False
        direction_mode = False

        ingredients = []
        directions = []
        for line in file.replace('\r', '').replace('\n\n', '\n').split('\n'):
            if 'Titel:' in line:
                title = line.replace('Titel:', '').strip()
            if 'Kategorien:' in line:
                tags = line.replace('Kategorien:', '').strip()
            if ingredient_mode and ('quelle' in line.lower()
                                    or 'source' in line.lower() or
                                    (line == '' and len(ingredients) > 0)):
                ingredient_mode = False
                direction_mode = True
            if ingredient_mode:
                if line != '' and '===' not in line and 'Zubereitung' not in line:
                    ingredients.append(line.strip())
            if direction_mode:
                if line.strip() != '' and line.strip() != '=====':
                    directions.append(line.strip())
            if 'Zutaten:' in line or 'Ingredients' in line or 'Menge:' in line:
                ingredient_mode = True

        recipe = Recipe.objects.create(name=title,
                                       created_by=self.request.user,
                                       internal=True,
                                       space=self.request.space)

        for k in tags.split(','):
            keyword, created = Keyword.objects.get_or_create(
                name=k.strip(), space=self.request.space)
            recipe.keywords.add(keyword)

        step = Step.objects.create(
            instruction='  \n'.join(directions) + '\n\n',
            space=self.request.space,
        )

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in ingredients:
            if len(ingredient.strip()) > 0:
                amount, unit, food, note = ingredient_parser.parse(ingredient)
                f = ingredient_parser.get_food(food)
                u = ingredient_parser.get_unit(unit)
                step.ingredients.add(
                    Ingredient.objects.create(
                        food=f,
                        unit=u,
                        amount=amount,
                        note=note,
                        original_text=ingredient,
                        space=self.request.space,
                    ))
        recipe.steps.add(step)

        return recipe
Ejemplo n.º 5
0
    def get_recipe_from_file(self, file):
        source_url = ''

        ingredient_mode = 0

        ingredients = []
        directions = []
        for i, fl in enumerate(file.readlines(), start=0):
            line = fl.decode("utf-8")
            if i == 0:
                title = line.strip()
            else:
                if line.startswith('https:') or line.startswith('http:'):
                    source_url = line.strip()
                else:
                    if ingredient_mode == 1 and len(line.strip()) == 0:
                        ingredient_mode = 2
                    if re.match(r'^([0-9])[^.](.)*$',
                                line) and ingredient_mode < 2:
                        ingredient_mode = 1
                        ingredients.append(line.strip())
                    else:
                        directions.append(line.strip())

        recipe = Recipe.objects.create(
            name=title,
            created_by=self.request.user,
            internal=True,
            space=self.request.space,
        )

        step = Step.objects.create(
            instruction='\n'.join(directions),
            space=self.request.space,
        )

        if source_url != '':
            step.instruction += '\n' + source_url
            step.save()

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in ingredients:
            if len(ingredient.strip()) > 0:
                amount, unit, ingredient, note = ingredient_parser.parse(
                    ingredient)
                f = ingredient_parser.get_food(ingredient)
                u = ingredient_parser.get_unit(unit)
                step.ingredients.add(
                    Ingredient.objects.create(
                        food=f,
                        unit=u,
                        amount=amount,
                        note=note,
                        space=self.request.space,
                    ))
        recipe.steps.add(step)

        return recipe
Ejemplo n.º 6
0
    def get_recipe_from_file(self, file):

        recipe = Recipe.objects.create(name=file['name'].strip(),
                                       created_by=self.request.user,
                                       internal=True,
                                       space=self.request.space)

        try:
            if file['recipeYield'] != '':
                recipe.servings = int(file['recipeYield'])

            if file['totalTime'] != '':
                recipe.waiting_time = int(file['totalTime']) - int(
                    file['timePrep'])

            if file['prepTime'] != '':
                recipe.working_time = int(file['timePrep'])

            recipe.save()
        except Exception as e:
            print('failed to parse yield or time ', str(e))

        ingredient_parser = IngredientParser(self.request, True)
        ingredients_added = False
        for s in file['recipeInstructions']:
            step = Step.objects.create(
                instruction=s['text'],
                space=self.request.space,
            )
            if not ingredients_added:
                ingredients_added = True

                for ingredient in file['recipeIngredient']:
                    amount, unit, food, note = ingredient_parser.parse(
                        ingredient)
                    f = ingredient_parser.get_food(food)
                    u = ingredient_parser.get_unit(unit)
                    step.ingredients.add(
                        Ingredient.objects.create(
                            food=f,
                            unit=u,
                            amount=amount,
                            note=note,
                            original_text=ingredient,
                            space=self.request.space,
                        ))
            recipe.steps.add(step)

        if len(file['image']) > 0:
            try:
                response = requests.get(file['image'][0])
                self.import_recipe_image(recipe, BytesIO(response.content))
            except Exception as e:
                print('failed to import image ', str(e))

        return recipe
Ejemplo n.º 7
0
    def get_recipe_from_file(self, file):
        ingredient_mode = False
        direction_mode = False

        ingredients = []
        directions = []
        for fl in file.readlines():
            line = fl.decode("utf-8")
            if 'Title:' in line:
                title = line.replace('Title:', '').replace('"', '').strip()
            if 'Description:' in line:
                description = line.replace('Description:', '').strip()
            if 'Original URL:' in line or 'Source:' in line or 'Yield:' in line or 'Total:' in line:
                if len(line.strip().split(':')[1]) > 0:
                    directions.append(line.strip() + '\n')
            if ingredient_mode:
                if len(line) > 2 and 'Instructions:' not in line:
                    ingredients.append(line.strip())
            if direction_mode:
                if len(line) > 2:
                    directions.append(line.strip() + '\n')
            if 'Ingredients:' in line:
                ingredient_mode = True
            if 'Instructions:' in line:
                ingredient_mode = False
                direction_mode = True

        recipe = Recipe.objects.create(name=title,
                                       description=description,
                                       created_by=self.request.user,
                                       internal=True,
                                       space=self.request.space)

        step = Step.objects.create(
            instruction='\n'.join(directions) + '\n\n',
            space=self.request.space,
        )

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in ingredients:
            if len(ingredient.strip()) > 0:
                amount, unit, food, note = ingredient_parser.parse(ingredient)
                f = ingredient_parser.get_food(food)
                u = ingredient_parser.get_unit(unit)
                step.ingredients.add(
                    Ingredient.objects.create(
                        food=f,
                        unit=u,
                        amount=amount,
                        note=note,
                        original_text=ingredient,
                        space=self.request.space,
                    ))
        recipe.steps.add(step)

        return recipe
Ejemplo n.º 8
0
    def get_recipe_from_file(self, file):
        # 'file' comes is as a beautifulsoup object
        recipe = Recipe.objects.create(name=file.find("h2", {"itemprop": "name"}).text.strip(), created_by=self.request.user, internal=True, space=self.request.space, )

        # add 'Courses' and 'Categories' as keywords
        for course in file.find_all("span", {"itemprop": "recipeCourse"}):
            keyword, created = Keyword.objects.get_or_create(name=course.text, space=self.request.space)
            recipe.keywords.add(keyword)

        for category in file.find_all("meta", {"itemprop": "recipeCategory"}):
            keyword, created = Keyword.objects.get_or_create(name=category.get("content"), space=self.request.space)
            recipe.keywords.add(keyword)

        try:
            recipe.servings = parse_servings(file.find("span", {"itemprop": "recipeYield"}).text.strip())
            recipe.working_time = iso_duration_to_minutes(file.find("span", {"meta": "prepTime"}).text.strip())
            recipe.waiting_time = iso_duration_to_minutes(file.find("span", {"meta": "cookTime"}).text.strip())
            recipe.save()
        except AttributeError:
            pass

        step = Step.objects.create(instruction='', space=self.request.space,)

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in file.find("div", {"itemprop": "recipeIngredients"}).findChildren("p"):
            if ingredient.text == "":
                continue
            amount, unit, ingredient, note = ingredient_parser.parse(ingredient.text.strip())
            f = ingredient_parser.get_food(ingredient)
            u = ingredient_parser.get_unit(unit)
            step.ingredients.add(Ingredient.objects.create(
                food=f, unit=u, amount=amount, note=note, space=self.request.space,
            ))

        for s in file.find("div", {"itemprop": "recipeDirections"}).find_all("p"):
            if s.text == "":
                continue
            step.instruction += s.text + ' \n'

        if file.find("span", {"itemprop": "recipeSource"}).text != '':
            step.instruction += "\n\nImported from: " + file.find("span", {"itemprop": "recipeSource"}).text
            step.save()

        recipe.steps.add(step)

        # import the Primary recipe image that is stored in the Zip
        try:
            for f in self.files:
                if '.zip' in f['name']:
                    import_zip = ZipFile(f['file'])
                    self.import_recipe_image(recipe, BytesIO(import_zip.read(file.find("img", class_="recipe-photo").get("src"))), filetype='.jpeg')
        except Exception as e:
            print(recipe.name, ': failed to import image ', str(e))

        return recipe
Ejemplo n.º 9
0
    def get_recipe_from_file(self, file):

        recipe = Recipe.objects.create(name=file['name'].strip(),
                                       created_by=self.request.user,
                                       internal=True,
                                       space=self.request.space)

        if file['servings'] != '':
            recipe.servings = file['servings']

        if file['timeCook'] != '':
            recipe.waiting_time = file['timeCook']

        if file['timePrep'] != '':
            recipe.working_time = file['timePrep']

        recipe.save()

        step = Step.objects.create(
            instruction=file['directions'],
            space=self.request.space,
        )

        if file['source'] != '':
            step.instruction += '\n' + file['source']

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in file['ingredients'].split('\n'):
            if len(ingredient.strip()) > 0:
                amount, unit, food, note = ingredient_parser.parse(ingredient)
                f = ingredient_parser.get_food(food)
                u = ingredient_parser.get_unit(unit)
                step.ingredients.add(
                    Ingredient.objects.create(
                        food=f,
                        unit=u,
                        amount=amount,
                        note=note,
                        original_text=ingredient,
                        space=self.request.space,
                    ))
        recipe.steps.add(step)

        if file['image'] != '':
            self.import_recipe_image(
                recipe,
                BytesIO(
                    base64.b64decode(file['image'].replace(
                        'data:image/jpeg;base64,', ''))),
                filetype='.jpeg')

        return recipe
Ejemplo n.º 10
0
def test(request):
    if not settings.DEBUG:
        return HttpResponseRedirect(reverse('index'))

    from cookbook.helper.ingredient_parser import IngredientParser
    parser = IngredientParser(request, False)

    data = {
        'original': '1 LoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutlLoremipsumdolorsitametconsetetursadipscingelitrseddiamnonumyeirmodtemporinviduntutl'
    }
    data['parsed'] = parser.parse(data['original'])

    return render(request, 'test.html', {'data': data})
Ejemplo n.º 11
0
    def get_recipe_from_file(self, file):
        recipe_json = json.loads(file.getvalue().decode("utf-8"))

        description = '' if len(recipe_json['description'].strip()) > 500 else recipe_json['description'].strip()

        recipe = Recipe.objects.create(
            name=recipe_json['name'].strip(), description=description,
            created_by=self.request.user, internal=True, space=self.request.space)

        # TODO parse times (given in PT2H3M )
        # @vabene check recipe_url_import.iso_duration_to_minutes  I think it does what you are looking for

        ingredients_added = False
        for s in recipe_json['recipe_instructions']:
            step = Step.objects.create(
                instruction=s['text'], space=self.request.space,
            )
            if not ingredients_added:
                ingredients_added = True

                if len(recipe_json['description'].strip()) > 500:
                    step.instruction = recipe_json['description'].strip() + '\n\n' + step.instruction

                ingredient_parser = IngredientParser(self.request, True)
                for ingredient in recipe_json['recipe_ingredient']:
                    try:
                        if ingredient['food']:
                            f = ingredient_parser.get_food(ingredient['food'])
                            u = ingredient_parser.get_unit(ingredient['unit'])
                            amount = ingredient['quantity']
                            note = ingredient['note']
                        else:
                            amount, unit, ingredient, note = ingredient_parser.parse(ingredient['note'])
                            f = ingredient_parser.get_food(ingredient)
                            u = ingredient_parser.get_unit(unit)
                        step.ingredients.add(Ingredient.objects.create(
                            food=f, unit=u, amount=amount, note=note, space=self.request.space,
                        ))
                    except Exception:
                        pass
            recipe.steps.add(step)

        for f in self.files:
            if '.zip' in f['name']:
                import_zip = ZipFile(f['file'])
                try:
                    self.import_recipe_image(recipe, BytesIO(import_zip.read(f'recipes/{recipe_json["slug"]}/images/min-original.webp')), filetype=get_filetype(f'recipes/{recipe_json["slug"]}/images/original'))
                except Exception:
                    pass

        return recipe
Ejemplo n.º 12
0
def ingredient_from_string(request):
    text = request.POST['text']

    ingredient_parser = IngredientParser(request, False)
    amount, unit, food, note = ingredient_parser.parse(text)

    return JsonResponse(
        {
            'amount': amount,
            'unit': unit,
            'food': food,
            'note': note
        },
        status=200)
Ejemplo n.º 13
0
    def get_recipe_from_file(self, file):

        # Create initial recipe with just a title and a description
        recipe = Recipe.objects.create(
            name=file['title'],
            created_by=self.request.user,
            internal=True,
            space=self.request.space,
        )

        # set the description as an empty string for later use for the source URL, in case there is no description text.
        recipe.description = ''

        try:
            if file['description'] != '':
                recipe.description = file['description'].strip()
        except Exception as e:
            print(recipe.name, ': failed to parse recipe description ', str(e))

        instructions = file['instructions']
        if not instructions:
            instructions = ''

        step = Step.objects.create(
            instruction=instructions,
            space=self.request.space,
        )

        # Append the original import url to the step (if it exists)
        try:
            if file['url'] != '':
                step.instruction += '\n\n' + _(
                    'Imported from') + ': ' + file['url']
                step.save()
        except Exception as e:
            print(recipe.name, ': failed to import source url ', str(e))

        try:
            # Process the ingredients. Assumes 1 ingredient per line.
            ingredient_parser = IngredientParser(self.request, True)
            for ingredient in file['ingredients'].split('\n'):
                if len(ingredient.strip()) > 0:
                    amount, unit, food, note = ingredient_parser.parse(food)
                    f = ingredient_parser.get_food(ingredient)
                    u = ingredient_parser.get_unit(unit)
                    step.ingredients.add(
                        Ingredient.objects.create(
                            food=f,
                            unit=u,
                            amount=amount,
                            note=note,
                            original_text=ingredient,
                            space=self.request.space,
                        ))
        except Exception as e:
            print(recipe.name, ': failed to parse recipe ingredients ', str(e))
        recipe.steps.add(step)

        # Attempt to import prep/cooking times
        # quick hack, this assumes only one number in the quantity field.
        try:
            if file['quantity'] != '':
                for item in file['quantity'].split(' '):
                    if item.isdigit():
                        recipe.servings = int(item)
                        break
        except Exception as e:
            print(recipe.name, ': failed to parse quantity ', str(e))

        try:
            if file['totalTime'] != '':
                recipe.waiting_time = int(file['totalTime'])
        except Exception as e:
            print(recipe.name, ': failed to parse total times ', str(e))

        try:
            if file['preparationTime'] != '':
                recipe.working_time = int(file['preparationTime'])
        except Exception as e:
            print(recipe.name, ': failed to parse prep time ', str(e))

        try:
            if file['cookingTime'] != '':
                recipe.waiting_time = int(file['cookingTime'])
        except Exception as e:
            print(recipe.name, ': failed to parse cooking time ', str(e))

        recipe.save()

        # Import the recipe keywords
        try:
            if file['keywords'] != '':
                for keyword in file['keywords'].split(';'):
                    k, created = Keyword.objects.get_or_create(
                        name=keyword.strip(), space=self.request.space)
                    recipe.keywords.add(k)
            recipe.save()
        except Exception as e:
            print(recipe.name, ': failed to parse keywords ', str(e))

        # TODO: Parse Nutritional Information

        # Import the original image from the zip file, if we cannot do that, attempt to download it again.
        try:
            if file['pictures'][0] != '':
                image_file_name = file['pictures'][0].split('/')[-1]
                for f in self.files:
                    if '.rtk' in f['name']:
                        import_zip = ZipFile(f['file'])
                        self.import_recipe_image(
                            recipe,
                            BytesIO(import_zip.read(image_file_name)),
                            filetype=get_filetype(image_file_name))
            else:
                if file['originalPicture'] != '':
                    response = requests.get(file['originalPicture'])
                    if imghdr.what(BytesIO(response.content)) is not None:
                        self.import_recipe_image(recipe,
                                                 BytesIO(response.content),
                                                 filetype=get_filetype(
                                                     file['originalPicture']))
                    else:
                        raise Exception("Original image failed to download.")
        except Exception as e:
            print(recipe.name, ': failed to import image ', str(e))

        return recipe
Ejemplo n.º 14
0
def test_ingredient_parser():
    expectations = {
        "2¼ l Wasser": (2.25, "l", "Wasser", ""),
        "2¼l Wasser": (2.25, "l", "Wasser", ""),
        "¼ l Wasser": (0.25, "l", "Wasser", ""),
        "3l Wasser": (3, "l", "Wasser", ""),
        "4 l Wasser": (4, "l", "Wasser", ""),
        "½l Wasser": (0.5, "l", "Wasser", ""),
        "⅛ Liter Sauerrahm": (0.125, "Liter", "Sauerrahm", ""),
        "5 Zwiebeln": (5, "", "Zwiebeln", ""),
        "3 Zwiebeln, gehackt": (3, "", "Zwiebeln", "gehackt"),
        "5 Zwiebeln (gehackt)": (5, "", "Zwiebeln", "gehackt"),
        "1 Zwiebel(n)": (1, "", "Zwiebel(n)", ""),
        "4 1/2 Zwiebeln": (4.5, "", "Zwiebeln", ""),
        "4 ½ Zwiebeln": (4.5, "", "Zwiebeln", ""),
        "1/2 EL Mehl": (0.5, "EL", "Mehl", ""),
        "1/2 Zwiebel": (0.5, "", "Zwiebel", ""),
        "1/5g Mehl, gesiebt": (0.2, "g", "Mehl", "gesiebt"),
        "1/2 Zitrone, ausgepresst": (0.5, "", "Zitrone", "ausgepresst"),
        "etwas Mehl": (0, "", "etwas Mehl", ""),
        "Öl zum Anbraten": (0, "", "Öl zum Anbraten", ""),
        "n. B. Knoblauch, zerdrückt": (0, "", "n. B. Knoblauch", "zerdrückt"),
        "Kräuter, mediterrane (Oregano, Rosmarin, Basilikum)":
        (0, "", "Kräuter, mediterrane", "Oregano, Rosmarin, Basilikum"),
        "600 g Kürbisfleisch (Hokkaido), geschält, entkernt und geraspelt":
        (600, "g", "Kürbisfleisch (Hokkaido)",
         "geschält, entkernt und geraspelt"),
        "Muskat": (0, "", "Muskat", ""),
        "200 g Mehl, glattes": (200, "g", "Mehl", "glattes"),
        "1 Ei(er)": (1, "", "Ei(er)", ""),
        "1 Prise(n) Salz": (1, "Prise(n)", "Salz", ""),
        "etwas Wasser, lauwarmes": (0, "", "etwas Wasser", "lauwarmes"),
        "Strudelblätter, fertige, für zwei Strudel":
        (0, "", "Strudelblätter", "fertige, für zwei Strudel"),
        "barrel-aged Bourbon": (0, "", "barrel-aged Bourbon", ""),
        "golden syrup": (0, "", "golden syrup", ""),
        "unsalted butter, for greasing":
        (0, "", "unsalted butter", "for greasing"),
        "unsalted butter , for greasing": (0, "", "unsalted butter",
                                           "for greasing"),  # trim
        "1 small sprig of fresh rosemary": (1, "small",
                                            "sprig of fresh rosemary", ""),
        # does not always work perfectly!
        "75 g fresh breadcrumbs": (75, "g", "fresh breadcrumbs", ""),
        "4 acorn squash , or onion squash (600-800g)":
        (4, "acorn", "squash , or onion squash", "600-800g"),
        "1 x 250 g packet of cooked mixed grains , such as spelt and wild rice":
        (1, "x", "250 g packet of cooked mixed grains",
         "such as spelt and wild rice"),
        "1 big bunch of fresh mint , (60g)": (1, "big",
                                              "bunch of fresh mint ,", "60g"),
        "1 large red onion": (1, "large", "red onion", ""),
        # "2-3 TL Curry": (), # idk what it should use here either
        "1 Zwiebel gehackt": (1, "Zwiebel", "gehackt", ""),
        "1 EL Kokosöl": (1, "EL", "Kokosöl", ""),
        "0.5 paket jäst (à 50 g)": (0.5, "paket", "jäst", "à 50 g"),
        "ägg": (0, "", "ägg", ""),
        "50 g smör eller margarin": (50, "g", "smör eller margarin", ""),
        "3,5 l Wasser": (3.5, "l", "Wasser", ""),
        "3.5 l Wasser": (3.5, "l", "Wasser", ""),
        "400 g Karotte(n)": (400, "g", "Karotte(n)", ""),
        "400g unsalted butter": (400, "g", "butter", "unsalted"),
        "2L Wasser": (2, "L", "Wasser", ""),
        "1 (16 ounce) package dry lentils, rinsed":
        (1, "package", "dry lentils, rinsed", "16 ounce"),
        "2-3 c Water": (2, "c", "Water", "2-3"),
        "Pane (raffermo o secco) 80 g":
        (0, "", "Pane 80 g", "raffermo o secco"
         ),  # TODO this is actually not a good result but currently expected
    }
    # for German you could say that if an ingredient does not have
    # an amount # and it starts with a lowercase letter, then that
    # is a unit ("etwas", "evtl.") does not apply to English tho

    ingredient_parser = IngredientParser(None, False, ignore_automations=True)

    count = 0
    for key, val in expectations.items():
        count += 1
        parsed = ingredient_parser.parse(key)
        assert val == parsed
Ejemplo n.º 15
0
    def get_recipe_from_file(self, file):
        # 'file' comes is as a beautifulsoup object
        recipe = Recipe.objects.create(name=file.find("div", {"id": "name"}).text.strip(), created_by=self.request.user, internal=True, space=self.request.space, )

        for category in file.find_all("span", {"class": "recipeCategory"}):
            keyword, created = Keyword.objects.get_or_create(name=category.text, space=self.request.space)
            recipe.keywords.add(keyword)

        try:
            recipe.servings = parse_servings(file.find("a", {"id": "recipeYield"}).text.strip())
            recipe.working_time = iso_duration_to_minutes(file.find("span", {"meta": "prepTime"}).text.strip())
            recipe.waiting_time = iso_duration_to_minutes(file.find("span", {"meta": "cookTime"}).text.strip())
            recipe.description = (file.find("div ", {"id": "description"}).text.strip())[:512]

        except AttributeError:
            pass

        try:
            if len(file.find("span", {"id": "starred"}).text.strip()) > 0:
                recipe.keywords.add(Keyword.objects.get_or_create(space=self.request.space, name=_('Favorite'))[0])
        except AttributeError:
            pass

        step = Step.objects.create(instruction='', space=self.request.space, )

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in file.find_all("li", {"class": "recipeIngredient"}):
            if ingredient.text == "":
                continue
            amount, unit, food, note = ingredient_parser.parse(ingredient.text.strip())
            f = ingredient_parser.get_food(food)
            u = ingredient_parser.get_unit(unit)
            step.ingredients.add(Ingredient.objects.create(
                food=f, unit=u, amount=amount, note=note, original_text=ingredient.text.strip(), space=self.request.space,
            ))

        for s in file.find_all("li", {"class": "instruction"}):
            if s.text == "":
                continue
            step.instruction += s.text.strip() + ' \n\n'

        for s in file.find_all("li", {"class": "recipeNote"}):
            if s.text == "":
                continue
            step.instruction += s.text.strip() + ' \n\n'

        try:
            if file.find("a", {"id": "original_link"}).text != '':
                step.instruction += "\n\n" + _("Imported from") + ": " + file.find("a", {"id": "original_link"}).text
                step.save()
        except AttributeError:
            pass

        recipe.steps.add(step)

        # import the Primary recipe image that is stored in the Zip
        try:
            for f in self.files:
                if '.zip' in f['name']:
                    import_zip = ZipFile(f['file'])
                    self.import_recipe_image(recipe, BytesIO(import_zip.read(file.find("img", class_="recipeImage").get("src"))), filetype='.jpeg')
        except Exception as e:
            print(recipe.name, ': failed to import image ', str(e))

        recipe.save()
        return recipe
Ejemplo n.º 16
0
    def get_recipe_from_file(self, file):
        recipe_json = file

        recipe = Recipe.objects.create(name=recipe_json['title'].strip(),
                                       created_by=self.request.user,
                                       internal=True,
                                       space=self.request.space)

        if 'yield' in recipe_json:
            recipe.servings = parse_servings(recipe_json['yield'])

        if 'cookTime' in recipe_json:
            recipe.waiting_time = parse_time(recipe_json['cookTime'])

        if 'prepTime' in recipe_json:
            recipe.working_time = parse_time(recipe_json['prepTime'])

        if 'favorite' in recipe_json and recipe_json['favorite']:
            recipe.keywords.add(
                Keyword.objects.get_or_create(space=self.request.space,
                                              name=_('Favorite'))[0])

        if 'categories' in recipe_json:
            try:
                for x in recipe_json['categories']:
                    recipe.keywords.add(
                        Keyword.objects.get_or_create(space=self.request.space,
                                                      name=x)[0])
            except Exception:
                pass

        instruction = ''
        if 'text' in recipe_json:
            instruction += f'*{recipe_json["text"].strip()}*  \n'

        if 'instructions' in recipe_json:
            instruction += recipe_json["instructions"].strip() + '  \n'

        if 'notes' in recipe_json:
            instruction += recipe_json["notes"].strip() + '  \n'

        if 'link' in recipe_json:
            recipe.source_url = recipe_json['link']

        step = Step.objects.create(
            instruction=instruction,
            space=self.request.space,
        )

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in recipe_json['ingredients'].split('\n'):
            if ingredient.strip() != '':
                amount, unit, food, note = ingredient_parser.parse(ingredient)
                f = ingredient_parser.get_food(food)
                u = ingredient_parser.get_unit(unit)
                step.ingredients.add(
                    Ingredient.objects.create(
                        food=f,
                        unit=u,
                        amount=amount,
                        note=note,
                        original_text=ingredient,
                        space=self.request.space,
                    ))
        recipe.steps.add(step)

        if recipe_json.get("images", None):
            try:
                self.import_recipe_image(
                    recipe,
                    BytesIO(base64.b64decode(recipe_json['images'][0])),
                    filetype='.jpeg')
            except Exception:
                pass

        return recipe
Ejemplo n.º 17
0
            'ingredients': [],
        })

    if len(
            parse_description(description)
    ) > 256:  # split at 256 as long descriptions dont look good on recipe cards
        recipe_json['steps'][0][
            'instruction'] = f'*{parse_description(description)}*  \n\n' + recipe_json[
                'steps'][0]['instruction']
    else:
        recipe_json['description'] = parse_description(description)[:512]

    try:
        for x in scrape.ingredients():
            try:
                amount, unit, ingredient, note = ingredient_parser.parse(x)
                ingredient = {
                    'amount': amount,
                    'food': {
                        'name': ingredient,
                    },
                    'unit': None,
                    'note': note,
                    'original_text': x
                }
                if unit:
                    ingredient['unit'] = {
                        'name': unit,
                    }
                recipe_json['steps'][0]['ingredients'].append(ingredient)
            except Exception:
Ejemplo n.º 18
0
    def get_recipe_from_file(self, file):
        ingredient_mode = False
        direction_mode = False

        image_url = None
        tags = None
        ingredients = []
        directions = []
        description = ''
        for line in file.replace('\r', '').split('\n'):
            if line.strip() != '':
                if 'Title:' in line:
                    title = line.replace('Title:', '').replace('"', '').strip()
                if 'Description:' in line:
                    description = line.replace('Description:', '').strip()
                if 'Source:' in line or 'Serves:' in line or 'Prep Time:' in line or 'Cook Time:' in line:
                    directions.append(line.strip() + '\n')
                if 'Photo Url:' in line:
                    image_url = line.replace('Photo Url:', '').strip()
                if 'Tags:' in line:
                    tags = line.replace('Tags:', '').strip()
                if ingredient_mode:
                    if len(line) > 2 and 'Instructions:' not in line:
                        ingredients.append(line.strip())
                if direction_mode:
                    if len(line) > 2:
                        directions.append(line.strip() + '\n')
                if 'Ingredients:' in line:
                    ingredient_mode = True
                if 'Directions:' in line:
                    ingredient_mode = False
                    direction_mode = True

        recipe = Recipe.objects.create(name=title,
                                       description=description,
                                       created_by=self.request.user,
                                       internal=True,
                                       space=self.request.space)

        step = Step.objects.create(
            instruction='\n'.join(directions) + '\n\n',
            space=self.request.space,
        )

        if tags:
            for k in tags.split(','):
                keyword, created = Keyword.objects.get_or_create(
                    name=k.strip(), space=self.request.space)
                recipe.keywords.add(keyword)

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in ingredients:
            if len(ingredient.strip()) > 0:
                amount, unit, ingredient, note = ingredient_parser.parse(
                    ingredient)
                f = ingredient_parser.get_food(ingredient)
                u = ingredient_parser.get_unit(unit)
                step.ingredients.add(
                    Ingredient.objects.create(
                        food=f,
                        unit=u,
                        amount=amount,
                        note=note,
                        space=self.request.space,
                    ))
        recipe.steps.add(step)

        if image_url:
            try:
                response = requests.get(image_url)
                self.import_recipe_image(recipe, BytesIO(response.content))
            except Exception as e:
                print('failed to import image ', str(e))

        return recipe
Ejemplo n.º 19
0
    def get_recipe_from_file(self, file):
        ingredient_mode = False
        direction_mode = False

        ingredients = []
        directions = []
        for fl in file.readlines():
            line = fl.decode("utf-8")
            if 'Title:' in line:
                title = line.replace('Title:', '').strip()
            if 'Description:' in line:
                description = line.replace('Description:', '').strip()
            if 'Yield:' in line:
                directions.append(
                    _('Servings') + ' ' + line.replace('Yield:', '').strip() +
                    '\n')
            if 'Cook:' in line:
                directions.append(
                    _('Waiting time') + ' ' +
                    line.replace('Cook:', '').strip() + '\n')
            if 'Prep:' in line:
                directions.append(
                    _('Preparation Time') + ' ' +
                    line.replace('Prep:', '').strip() + '\n')
            if 'Cookbook:' in line:
                directions.append(
                    _('Cookbook') + ' ' +
                    line.replace('Cookbook:', '').strip() + '\n')
            if 'Section:' in line:
                directions.append(
                    _('Section') + ' ' + line.replace('Section:', '').strip() +
                    '\n')
            if ingredient_mode:
                if len(line) > 2 and 'Instructions:' not in line:
                    ingredients.append(line.strip())
            if direction_mode:
                if len(line) > 2:
                    directions.append(line.strip())
            if 'Ingredients:' in line:
                ingredient_mode = True
            if 'Instructions:' in line:
                ingredient_mode = False
                direction_mode = True

        recipe = Recipe.objects.create(
            name=title,
            description=description,
            created_by=self.request.user,
            internal=True,
            space=self.request.space,
        )

        step = Step.objects.create(
            instruction='\n'.join(directions),
            space=self.request.space,
        )

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in ingredients:
            amount, unit, ingredient, note = ingredient_parser.parse(
                ingredient)
            f = ingredient_parser.get_food(ingredient)
            u = ingredient_parser.get_unit(unit)
            step.ingredients.add(
                Ingredient.objects.create(
                    food=f,
                    unit=u,
                    amount=amount,
                    note=note,
                    space=self.request.space,
                ))
        recipe.steps.add(step)

        return recipe
Ejemplo n.º 20
0
def get_from_scraper(scrape, request):
    # converting the scrape_me object to the existing json format based on ld+json
    recipe_json = {}
    try:
        recipe_json['name'] = parse_name(scrape.title() or None)
    except Exception:
        recipe_json['name'] = None
    if not recipe_json['name']:
        try:
            recipe_json['name'] = scrape.schema.data.get('name') or ''
        except Exception:
            recipe_json['name'] = ''

    try:
        description = scrape.schema.data.get("description") or ''
    except Exception:
        description = ''

    recipe_json['description'] = parse_description(description)

    try:
        servings = scrape.yields() or None
    except Exception:
        servings = None
    if not servings:
        try:
            servings = scrape.schema.data.get('recipeYield') or 1
        except Exception:
            servings = 1
    if type(servings) != int:
        try:
            servings = int(re.findall(r'\b\d+\b', servings)[0])
        except Exception:
            servings = 1
    recipe_json['servings'] = max(servings, 1)

    try:
        recipe_json['prepTime'] = get_minutes(
            scrape.schema.data.get("prepTime")) or 0
    except Exception:
        recipe_json['prepTime'] = 0
    try:
        recipe_json['cookTime'] = get_minutes(
            scrape.schema.data.get("cookTime")) or 0
    except Exception:
        recipe_json['cookTime'] = 0

    if recipe_json['cookTime'] + recipe_json['prepTime'] == 0:
        try:
            recipe_json['prepTime'] = get_minutes(scrape.total_time()) or 0
        except Exception:
            try:
                get_minutes(scrape.schema.data.get("totalTime")) or 0
            except Exception:
                pass

    try:
        recipe_json['image'] = parse_image(scrape.image()) or None
    except Exception:
        recipe_json['image'] = None
    if not recipe_json['image']:
        try:
            recipe_json['image'] = parse_image(
                scrape.schema.data.get('image')) or ''
        except Exception:
            recipe_json['image'] = ''

    keywords = []
    try:
        if scrape.schema.data.get("keywords"):
            keywords += listify_keywords(scrape.schema.data.get("keywords"))
    except Exception:
        pass
    try:
        if scrape.schema.data.get('recipeCategory'):
            keywords += listify_keywords(
                scrape.schema.data.get("recipeCategory"))
    except Exception:
        pass
    try:
        if scrape.schema.data.get('recipeCuisine'):
            keywords += listify_keywords(
                scrape.schema.data.get("recipeCuisine"))
    except Exception:
        pass
    try:
        recipe_json['keywords'] = parse_keywords(
            list(set(map(str.casefold, keywords))), request.space)
    except AttributeError:
        recipe_json['keywords'] = keywords

    ingredient_parser = IngredientParser(request, True)
    try:
        ingredients = []
        for x in scrape.ingredients():
            try:
                amount, unit, ingredient, note = ingredient_parser.parse(x)
                ingredients.append({
                    'amount': amount,
                    'unit': {
                        'text': unit,
                        'id': random.randrange(10000, 99999)
                    },
                    'ingredient': {
                        'text': ingredient,
                        'id': random.randrange(10000, 99999)
                    },
                    'note': note,
                    'original': x
                })
            except Exception:
                ingredients.append({
                    'amount': 0,
                    'unit': {
                        'text': '',
                        'id': random.randrange(10000, 99999)
                    },
                    'ingredient': {
                        'text': x,
                        'id': random.randrange(10000, 99999)
                    },
                    'note': '',
                    'original': x
                })
        recipe_json['recipeIngredient'] = ingredients
    except Exception:
        recipe_json['recipeIngredient'] = ingredients

    try:
        recipe_json['recipeInstructions'] = parse_instructions(
            scrape.instructions())
    except Exception:
        recipe_json['recipeInstructions'] = ""

    if scrape.url:
        recipe_json['url'] = scrape.url
        recipe_json['recipeInstructions'] += "\n\nImported from " + scrape.url
    return recipe_json
Ejemplo n.º 21
0
    def get_recipe_from_file(self, file):
        recipe_json = json.loads(file.getvalue().decode("utf-8"))

        description = '' if len(recipe_json['description'].strip(
        )) > 500 else recipe_json['description'].strip()

        recipe = Recipe.objects.create(name=recipe_json['name'].strip(),
                                       description=description,
                                       created_by=self.request.user,
                                       internal=True,
                                       servings=recipe_json['recipeYield'],
                                       space=self.request.space)

        try:
            recipe.working_time = iso_duration_to_minutes(
                recipe_json['prepTime'])
            recipe.waiting_time = iso_duration_to_minutes(
                recipe_json['cookTime'])
        except Exception:
            pass

        if 'url' in recipe_json:
            recipe.source_url = recipe_json['url'].strip()

        if 'recipeCategory' in recipe_json:
            try:
                recipe.keywords.add(
                    Keyword.objects.get_or_create(
                        space=self.request.space,
                        name=recipe_json['recipeCategory'])[0])
            except Exception:
                pass

        if 'keywords' in recipe_json:
            try:
                for x in recipe_json['keywords'].split(','):
                    if x.strip() != '':
                        recipe.keywords.add(
                            Keyword.objects.get_or_create(
                                space=self.request.space, name=x)[0])
            except Exception:
                pass

        ingredients_added = False
        for s in recipe_json['recipeInstructions']:
            step = Step.objects.create(
                instruction=s,
                space=self.request.space,
            )
            if not ingredients_added:
                if len(recipe_json['description'].strip()) > 500:
                    step.instruction = recipe_json['description'].strip(
                    ) + '\n\n' + step.instruction

                ingredients_added = True

                ingredient_parser = IngredientParser(self.request, True)
                for ingredient in recipe_json['recipeIngredient']:
                    amount, unit, food, note = ingredient_parser.parse(
                        ingredient)
                    f = ingredient_parser.get_food(food)
                    u = ingredient_parser.get_unit(unit)
                    step.ingredients.add(
                        Ingredient.objects.create(
                            food=f,
                            unit=u,
                            amount=amount,
                            note=note,
                            original_text=ingredient,
                            space=self.request.space,
                        ))
            recipe.steps.add(step)

        if 'nutrition' in recipe_json:
            try:
                recipe.nutrition.calories = recipe_json['nutrition'][
                    'calories'].replace(' kcal', '').replace(' ', '')
                recipe.nutrition.proteins = recipe_json['nutrition'][
                    'calories'].replace(' g',
                                        '').replace(',', '.').replace(' ', '')
                recipe.nutrition.fats = recipe_json['nutrition'][
                    'calories'].replace(' g',
                                        '').replace(',', '.').replace(' ', '')
                recipe.nutrition.carbohydrates = recipe_json['nutrition'][
                    'calories'].replace(' g',
                                        '').replace(',', '.').replace(' ', '')
            except Exception:
                pass

        for f in self.files:
            if '.zip' in f['name']:
                import_zip = ZipFile(f['file'])
                for z in import_zip.filelist:
                    if re.match(f'^(.)+{recipe.name}/full.jpg$', z.filename):
                        self.import_recipe_image(
                            recipe,
                            BytesIO(import_zip.read(z.filename)),
                            filetype=get_filetype(z.filename))

        return recipe
Ejemplo n.º 22
0
    def get_recipe_from_file(self, file):
        with gzip.open(file, 'r') as recipe_zip:
            recipe_json = json.loads(recipe_zip.read().decode("utf-8"))

            recipe = Recipe.objects.create(name=recipe_json['name'].strip(),
                                           created_by=self.request.user,
                                           internal=True,
                                           space=self.request.space)

            if 'description' in recipe_json:
                recipe.description = '' if len(
                    recipe_json['description'].strip(
                    )) > 500 else recipe_json['description'].strip()

            try:
                if 'servings' in recipe_json['servings']:
                    recipe.servings = parse_servings(recipe_json['servings'])
                    recipe.servings_text = parse_servings_text(
                        recipe_json['servings'])

                if len(recipe_json['cook_time'].strip()) > 0:
                    recipe.waiting_time = re.findall(
                        r'\d+', recipe_json['cook_time'])[0]

                if len(recipe_json['prep_time'].strip()) > 0:
                    recipe.working_time = re.findall(
                        r'\d+', recipe_json['prep_time'])[0]
            except Exception:
                pass

            recipe.save()

            instructions = recipe_json['directions']
            if recipe_json['notes'] and len(recipe_json['notes'].strip()) > 0:
                instructions += '\n\n### ' + _(
                    'Notes') + ' \n' + recipe_json['notes']

            if recipe_json['nutritional_info'] and len(
                    recipe_json['nutritional_info'].strip()) > 0:
                instructions += '\n\n### ' + _(
                    'Nutritional Information'
                ) + ' \n' + recipe_json['nutritional_info']

            try:
                if len(recipe_json['source'].strip()) > 0 or len(
                        recipe_json['source_url'].strip()) > 0:
                    instructions += '\n\n### ' + _(
                        'Source') + ' \n' + recipe_json['source'].strip(
                        ) + ' \n' + recipe_json['source_url'].strip()
            except AttributeError:
                pass

            step = Step.objects.create(
                instruction=instructions,
                space=self.request.space,
            )

            if 'description' in recipe_json and len(
                    recipe_json['description'].strip()) > 500:
                step.instruction = recipe_json['description'].strip(
                ) + '\n\n' + step.instruction

            if 'categories' in recipe_json:
                for c in recipe_json['categories']:
                    keyword, created = Keyword.objects.get_or_create(
                        name=c.strip(), space=self.request.space)
                    recipe.keywords.add(keyword)

            ingredient_parser = IngredientParser(self.request, True)
            try:
                for ingredient in recipe_json['ingredients'].split('\n'):
                    if len(ingredient.strip()) > 0:
                        amount, unit, food, note = ingredient_parser.parse(
                            ingredient)
                        f = ingredient_parser.get_food(food)
                        u = ingredient_parser.get_unit(unit)
                        step.ingredients.add(
                            Ingredient.objects.create(
                                food=f,
                                unit=u,
                                amount=amount,
                                note=note,
                                original_text=ingredient,
                                space=self.request.space,
                            ))
            except AttributeError:
                pass

            recipe.steps.add(step)

            if recipe_json.get("photo_data", None):
                self.import_recipe_image(
                    recipe,
                    BytesIO(base64.b64decode(recipe_json['photo_data'])),
                    filetype='.jpeg')

            return recipe
Ejemplo n.º 23
0
    def get_recipe_from_file(self, file):
        ingredient_mode = False
        direction_mode = False
        description_mode = False

        ingredients = []
        directions = []
        descriptions = []
        for fl in file.readlines():
            line = fl.decode("utf-8")
            if 'title:' in line:
                title = line.replace('title:', '').replace('"', '').strip()
            if 'image:' in line:
                image = line.replace('image:', '').strip()
            if 'tags:' in line:
                tags = line.replace('tags:', '').strip()
            if ingredient_mode:
                if len(line) > 2 and 'directions:' not in line:
                    ingredients.append(line[2:])
            if '---' in line and direction_mode:
                direction_mode = False
                description_mode = True
            if direction_mode:
                if len(line) > 2:
                    directions.append(line[2:])
            if 'ingredients:' in line:
                ingredient_mode = True
            if 'directions:' in line:
                ingredient_mode = False
                direction_mode = True
            if description_mode and len(line) > 3 and '---' not in line:
                descriptions.append(line)

        recipe = Recipe.objects.create(name=title, created_by=self.request.user, internal=True, space=self.request.space)

        for k in tags.split(','):
            print(f'adding keyword {k.strip()}')
            keyword, created = Keyword.objects.get_or_create(name=k.strip(), space=self.request.space)
            recipe.keywords.add(keyword)

        step = Step.objects.create(
            instruction='\n'.join(directions) + '\n\n' + '\n'.join(descriptions), space=self.request.space,
        )

        ingredient_parser = IngredientParser(self.request, True)
        for ingredient in ingredients:
            amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
            f = ingredient_parser.get_food(ingredient)
            u = ingredient_parser.get_unit(unit)
            step.ingredients.add(Ingredient.objects.create(
                food=f, unit=u, amount=amount, note=note, space=self.request.space,
            ))
        recipe.steps.add(step)

        for f in self.files:
            if '.zip' in f['name']:
                import_zip = ZipFile(f['file'])
                for z in import_zip.filelist:
                    if re.match(f'^images/{image}$', z.filename):
                        self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename)), filetype=get_filetype(z.filename))

        return recipe
Ejemplo n.º 24
0
    def get_recipe_from_file(self, file):
        recipe_xml = file

        recipe = Recipe.objects.create(
            name=recipe_xml.find('title').text.strip(),
            created_by=self.request.user,
            internal=True,
            space=self.request.space)

        if recipe_xml.find('preptime') is not None:
            recipe.working_time = parse_time(
                recipe_xml.find('preptime').text.strip())

        if recipe_xml.find('cooktime') is not None:
            recipe.waiting_time = parse_time(
                recipe_xml.find('cooktime').text.strip())

        if recipe_xml.find('quantity') is not None:
            recipe.servings = parse_servings(
                recipe_xml.find('quantity').text.strip())
            recipe.servings_text = parse_servings_text(
                recipe_xml.find('quantity').text.strip())

        if recipe_xml.find('url') is not None:
            recipe.source_url = recipe_xml.find('url').text.strip()

        if recipe_xml.find(
                'description'
        ) is not None:  # description is a list of <li>'s with text
            if len(recipe_xml.find('description')) > 0:
                recipe.description = recipe_xml.find(
                    'description')[0].text[:512]

        for step in recipe_xml.find('recipetext').getchildren():
            step = Step.objects.create(
                instruction=step.text.strip(),
                space=self.request.space,
            )
            recipe.steps.add(step)

        ingredient_parser = IngredientParser(self.request, True)

        for ingredient in recipe_xml.find('ingredient').getchildren():
            if ingredient.text.strip() != '':
                amount, unit, food, note = ingredient_parser.parse(
                    ingredient.text.strip())
                f = ingredient_parser.get_food(food)
                u = ingredient_parser.get_unit(unit)
                recipe.steps.first().ingredients.add(
                    Ingredient.objects.create(
                        food=f,
                        unit=u,
                        amount=amount,
                        note=note,
                        original_text=ingredient.text.strip(),
                        space=self.request.space,
                    ))

        if recipe_xml.find('imageurl') is not None:
            try:
                response = requests.get(
                    recipe_xml.find('imageurl').text.strip())
                self.import_recipe_image(recipe, BytesIO(response.content))
            except Exception as e:
                print('failed to import image ', str(e))

        recipe.save()

        return recipe