This commit is contained in:
vabene1111
2023-01-03 23:12:00 +01:00
parent 56252a707a
commit 6176eeb024
13 changed files with 1209 additions and 985 deletions

View File

@@ -28,7 +28,7 @@ class IngredientParser:
self.food_aliases = c
caches['default'].touch(FOOD_CACHE_KEY, 30)
else:
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.FOOD_ALIAS).only('param_1', 'param_2').all():
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.FOOD_ALIAS).only('param_1', 'param_2').order_by('order').all():
self.food_aliases[a.param_1] = a.param_2
caches['default'].set(FOOD_CACHE_KEY, self.food_aliases, 30)
@@ -37,7 +37,7 @@ class IngredientParser:
self.unit_aliases = c
caches['default'].touch(UNIT_CACHE_KEY, 30)
else:
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.UNIT_ALIAS).only('param_1', 'param_2').all():
for a in Automation.objects.filter(space=self.request.space, disabled=False, type=Automation.UNIT_ALIAS).only('param_1', 'param_2').order_by('order').all():
self.unit_aliases[a.param_1] = a.param_2
caches['default'].set(UNIT_CACHE_KEY, self.unit_aliases, 30)
else:
@@ -59,7 +59,7 @@ class IngredientParser:
except KeyError:
return food
else:
if automation := Automation.objects.filter(space=self.request.space, type=Automation.FOOD_ALIAS, param_1=food, disabled=False).first():
if automation := Automation.objects.filter(space=self.request.space, type=Automation.FOOD_ALIAS, param_1=food, disabled=False).order_by('order').first():
return automation.param_2
return food
@@ -78,7 +78,7 @@ class IngredientParser:
except KeyError:
return unit
else:
if automation := Automation.objects.filter(space=self.request.space, type=Automation.UNIT_ALIAS, param_1=unit, disabled=False).first():
if automation := Automation.objects.filter(space=self.request.space, type=Automation.UNIT_ALIAS, param_1=unit, disabled=False).order_by('order').first():
return automation.param_2
return unit

View File

@@ -12,7 +12,8 @@ from recipe_scrapers._utils import get_host_name, get_minutes
from cookbook.helper import recipe_url_import as helper
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.models import Keyword
from cookbook.models import Keyword, Automation
# from recipe_scrapers._utils import get_minutes ## temporary until/unless upstream incorporates get_minutes() PR
@@ -121,7 +122,7 @@ def get_from_scraper(scrape, request):
try:
keywords.append(source_url.replace('http://', '').replace('https://', '').split('/')[0])
except Exception:
pass
recipe_json['source_url'] = ''
try:
recipe_json['keywords'] = parse_keywords(list(set(map(str.casefold, keywords))), request.space)
@@ -139,10 +140,18 @@ def get_from_scraper(scrape, request):
if len(recipe_json['steps']) == 0:
recipe_json['steps'].append({'instruction': '', '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']
parsed_description = parse_description(description)
# TODO notify user about limit if reached
# limits exist to limit the attack surface for dos style attacks
automations = Automation.objects.filter(type=Automation.DESCRIPTION_REPLACE, space=request.space, disabled=False).only('param_1', 'param_2', 'param_3').all().order_by('order')[:512]
for a in automations:
if re.match(a.param_1, (recipe_json['source_url'])[:512]):
parsed_description = re.sub(a.param_2, a.param_3, parsed_description, count=1)
if len(parsed_description) > 256: # split at 256 as long descriptions don't look good on recipe cards
recipe_json['steps'][0]['instruction'] = f'*{parsed_description}* \n\n' + recipe_json['steps'][0]['instruction']
else:
recipe_json['description'] = parse_description(description)[:512]
recipe_json['description'] = parsed_description[:512]
try:
for x in scrape.ingredients():
@@ -175,6 +184,12 @@ def get_from_scraper(scrape, request):
except Exception:
pass
if recipe_json['source_url']:
automations = Automation.objects.filter(type=Automation.DESCRIPTION_REPLACE, space=request.space, disabled=False).only('param_1', 'param_2', 'param_3').order_by('order').all()[:512]
for a in automations:
if re.match(a.param_1, (recipe_json['source_url'])[:512]):
recipe_json['description'] = re.sub(a.param_2, a.param_3, recipe_json['description'], count=1)
return recipe_json

View File

@@ -0,0 +1,23 @@
# Generated by Django 4.1.4 on 2023-01-03 21:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cookbook', '0185_food_plural_name_ingredient_always_use_plural_food_and_more'),
]
operations = [
migrations.AddField(
model_name='automation',
name='order',
field=models.IntegerField(default=1000),
),
migrations.AlterField(
model_name='automation',
name='type',
field=models.CharField(choices=[('FOOD_ALIAS', 'Food Alias'), ('UNIT_ALIAS', 'Unit Alias'), ('KEYWORD_ALIAS', 'Keyword Alias'), ('DESCRIPTION_REPLACE', 'Description Replace'), ('INSTRUCTION_REPLACE', 'Instruction Replace')], max_length=128),
),
]

View File

@@ -367,7 +367,7 @@ class UserPreference(models.Model, PermissionModelMixin):
)
user = AutoOneToOneField(User, on_delete=models.CASCADE, primary_key=True)
image = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True,blank=True, related_name='user_image')
image = models.ForeignKey("UserFile", on_delete=models.SET_NULL, null=True, blank=True, related_name='user_image')
theme = models.CharField(choices=THEMES, max_length=128, default=TANDOOR)
nav_color = models.CharField(choices=COLORS, max_length=128, default=PRIMARY)
default_unit = models.CharField(max_length=32, default='g')
@@ -1223,9 +1223,12 @@ class Automation(ExportModelOperationsMixin('automations'), models.Model, Permis
FOOD_ALIAS = 'FOOD_ALIAS'
UNIT_ALIAS = 'UNIT_ALIAS'
KEYWORD_ALIAS = 'KEYWORD_ALIAS'
DESCRIPTION_REPLACE = 'DESCRIPTION_REPLACE'
INSTRUCTION_REPLACE = 'INSTRUCTION_REPLACE'
type = models.CharField(max_length=128,
choices=((FOOD_ALIAS, _('Food Alias')), (UNIT_ALIAS, _('Unit Alias')), (KEYWORD_ALIAS, _('Keyword Alias')),))
choices=((FOOD_ALIAS, _('Food Alias')), (UNIT_ALIAS, _('Unit Alias')), (KEYWORD_ALIAS, _('Keyword Alias')),
(DESCRIPTION_REPLACE, _('Description Replace')), (INSTRUCTION_REPLACE, _('Instruction Replace')),))
name = models.CharField(max_length=128, default='')
description = models.TextField(blank=True, null=True)
@@ -1233,6 +1236,8 @@ class Automation(ExportModelOperationsMixin('automations'), models.Model, Permis
param_2 = models.CharField(max_length=128, blank=True, null=True)
param_3 = models.CharField(max_length=128, blank=True, null=True)
order = models.IntegerField(default=1000)
disabled = models.BooleanField(default=False)
updated_at = models.DateTimeField(auto_now=True)

View File

@@ -876,11 +876,11 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer):
value = value.quantize(
Decimal(1)) if value == value.to_integral() else value.normalize() # strips trailing zero
return (
obj.name
or getattr(obj.mealplan, 'title', None)
or (d := getattr(obj.mealplan, 'date', None)) and ': '.join([obj.mealplan.recipe.name, str(d)])
or obj.recipe.name
) + f' ({value:.2g})'
obj.name
or getattr(obj.mealplan, 'title', None)
or (d := getattr(obj.mealplan, 'date', None)) and ': '.join([obj.mealplan.recipe.name, str(d)])
or obj.recipe.name
) + f' ({value:.2g})'
def update(self, instance, validated_data):
# TODO remove once old shopping list
@@ -1067,7 +1067,7 @@ class AutomationSerializer(serializers.ModelSerializer):
class Meta:
model = Automation
fields = (
'id', 'type', 'name', 'description', 'param_1', 'param_2', 'param_3', 'disabled', 'created_by',)
'id', 'type', 'name', 'description', 'param_1', 'param_2', 'param_3', 'order', 'disabled', 'created_by',)
read_only_fields = ('created_by',)

View File

@@ -72,3 +72,13 @@ def test_recipe_import(arg, u1_s1):
content_type='application/json')
recipe = json.loads(response.content)['recipe_json']
validate_recipe(arg, recipe)
# def test_description_replace_automation():
# if 'cookbook' in os.getcwd():
# test_file = os.path.join(os.getcwd(), 'other', 'test_data', 'chefkoch2.html')
# else:
# test_file = os.path.join(os.getcwd(), 'cookbook', 'tests', 'other', 'test_data', 'chefkoch2.html')
#
# with open(test_file, 'r', encoding='UTF-8') as d:
# pass