Add phase 5: link import, Instagram fallback and share target
- SSRF-safe fetcher: public IPs only, connects to the checked address, redirects re-validated, size/time limits, honest user agent - schema.org/Recipe JSON-LD extraction (graphs, HowToSections, ISO durations, yields, keywords, images) without extra dependencies; AI fallback on plain page text when no structured recipe exists - Instagram: one login-free request to the public embed page; when Instagram withholds the caption, the import page explains how to paste the text or import a screenshot instead - Suggested source photo can be downloaded and attached on save - Text import works without AI (text becomes the description) - Installable PWA with manifest, icons and Android share target - Offline tests for SSRF rules, parsers, Instagram and import views Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1bf8ef8b65
commit
60785e2437
+8
-1
@@ -59,6 +59,9 @@ class RecipeForm(forms.ModelForm):
|
||||
)
|
||||
source_url = forms.URLField(label="Quelle (URL)", required=False, max_length=1000, assume_scheme="https")
|
||||
photos = photo_field()
|
||||
# Link import: photo suggested by the source page, downloaded only when the user keeps the tick.
|
||||
import_image_url = forms.URLField(required=False, max_length=2000, widget=forms.HiddenInput, assume_scheme="https")
|
||||
use_import_image = forms.BooleanField(label="Bild der Quelle als Foto übernehmen", required=False, initial=True)
|
||||
|
||||
class Meta:
|
||||
model = Recipe
|
||||
@@ -74,7 +77,8 @@ class RecipeForm(forms.ModelForm):
|
||||
}
|
||||
|
||||
field_order = ["title", "description", "servings", "servings_label", "prep_minutes", "cook_minutes",
|
||||
"ingredients_text", "steps_text", "tags_text", "photos", "author_notes", "source_url", "visibility"]
|
||||
"ingredients_text", "steps_text", "tags_text", "use_import_image", "photos", "author_notes",
|
||||
"source_url", "visibility"]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -85,6 +89,9 @@ class RecipeForm(forms.ModelForm):
|
||||
self.initial.setdefault("ingredients_text", parsing.ingredients_to_text(recipe.ingredients.all()))
|
||||
self.initial.setdefault("steps_text", parsing.steps_to_text([s.text for s in recipe.steps.all()]))
|
||||
self.initial.setdefault("tags_text", ", ".join(t.name for t in recipe.tags.all()))
|
||||
if recipe.pk or not (self.initial.get("import_image_url") or self.data.get("import_image_url")):
|
||||
del self.fields["import_image_url"]
|
||||
del self.fields["use_import_image"]
|
||||
if recipe.pk:
|
||||
remaining = settings.IMAGE_MAX_PER_RECIPE - recipe.images.count()
|
||||
self.fields["photos"].label = "Weitere Fotos"
|
||||
|
||||
Reference in New Issue
Block a user