diff --git a/.github/workflows/partial-backend.yml b/.github/workflows/partial-backend.yml
index 80afa791eb6b..154d98626b51 100644
--- a/.github/workflows/partial-backend.yml
+++ b/.github/workflows/partial-backend.yml
@@ -67,7 +67,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
- sudo apt-get install libsasl2-dev libldap2-dev libssl-dev tesseract-ocr-all
+ sudo apt-get install libsasl2-dev libldap2-dev libssl-dev
poetry install
poetry add "psycopg2-binary==2.8.6"
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' || steps.cache-validate.outputs.cache-hit-success != 'true'
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 9594c0faffb2..919d27b7d007 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -50,7 +50,6 @@ RUN apt-get update \
build-essential \
libpq-dev \
libwebp-dev \
- tesseract-ocr-all \
# LDAP Dependencies
libsasl2-dev libldap2-dev libssl-dev \
gnupg gnupg2 gnupg1 \
@@ -89,8 +88,8 @@ RUN apt-get update \
&& apt-get install --no-install-recommends -y \
gosu \
iproute2 \
- tesseract-ocr-all \
libldap-common \
+ libldap-2.5 \
&& rm -rf /var/lib/apt/lists/*
# copying poetry and venv into image
diff --git a/docs/docs/documentation/getting-started/faq.md b/docs/docs/documentation/getting-started/faq.md
index 4a241003e684..cdc1227e8fab 100644
--- a/docs/docs/documentation/getting-started/faq.md
+++ b/docs/docs/documentation/getting-started/faq.md
@@ -64,9 +64,7 @@ No. Due to limitations from the Javascript Framework, mealie doesn't support ser
## Can I install Mealie without docker?
-Yes, you can install Mealie on your local machine. HOWEVER, it is recommended that you don't. Managing non-system versions of python, node, and npm is a pain. Moreover, updating and upgrading your system with this configuration is unsupported and will likely require manual interventions. If you insist on installing Mealie on your local machine, you can use the links below to help guide your path.
-
-- [Advanced Installation](../installation/advanced/)
+Yes, you can install Mealie on your local machine. HOWEVER, it is recommended that you don't. Managing non-system versions of python, node, and npm is a pain. Moreover, updating and upgrading your system with this configuration is unsupported and will likely require manual interventions.
## What is fuzzy search and how do I use it?
Mealie can use fuzzy search, which is robust to minor typos. For example, searching for "brocolli" will still find your recipe for "broccoli soup". But fuzzy search is only functional on a Postgres database backend. To enable fuzzy search you will need to migrate to Postgres:
diff --git a/docs/docs/documentation/getting-started/installation/postgres.md b/docs/docs/documentation/getting-started/installation/postgres.md
index fa88e8b6c912..f98f6b22a7ff 100644
--- a/docs/docs/documentation/getting-started/installation/postgres.md
+++ b/docs/docs/documentation/getting-started/installation/postgres.md
@@ -46,7 +46,7 @@ services:
image: postgres:15
restart: always
volumes:
- - ./mealie-pgdata:/var/lib/postgresql/data
+ - mealie-pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: mealie
POSTGRES_USER: mealie
diff --git a/docs/docs/overrides/api.html b/docs/docs/overrides/api.html
index a54d6bf3c398..83038e2aead5 100644
--- a/docs/docs/overrides/api.html
+++ b/docs/docs/overrides/api.html
@@ -14,7 +14,7 @@
diff --git a/frontend/components/Domain/Recipe/RecipeActionMenu.vue b/frontend/components/Domain/Recipe/RecipeActionMenu.vue
index c5b6a72e76cb..ad24e0ed8b13 100644
--- a/frontend/components/Domain/Recipe/RecipeActionMenu.vue
+++ b/frontend/components/Domain/Recipe/RecipeActionMenu.vue
@@ -102,7 +102,6 @@ const SAVE_EVENT = "save";
const DELETE_EVENT = "delete";
const CLOSE_EVENT = "close";
const JSON_EVENT = "json";
-const OCR_EVENT = "ocr";
export default defineComponent({
components: { RecipeContextMenu, RecipeFavoriteBadge, RecipeTimerMenu, RecipeTimelineBadge },
@@ -139,10 +138,6 @@ export default defineComponent({
type: Boolean,
default: false,
},
- showOcrButton: {
- type: Boolean,
- default: false,
- },
},
setup(props, context) {
const deleteDialog = ref(false);
@@ -175,15 +170,6 @@ export default defineComponent({
},
];
- if (props.showOcrButton) {
- editorButtons.splice(2, 0, {
- text: i18n.t("ocr-editor.ocr-editor"),
- icon: $globals.icons.eye,
- event: OCR_EVENT,
- color: "accent",
- });
- }
-
function emitHandler(event: string) {
switch (event) {
case CLOSE_EVENT:
diff --git a/frontend/components/Domain/Recipe/RecipeDialogShare.vue b/frontend/components/Domain/Recipe/RecipeDialogShare.vue
index d62ccfc9843c..f64aa341588b 100644
--- a/frontend/components/Domain/Recipe/RecipeDialogShare.vue
+++ b/frontend/components/Domain/Recipe/RecipeDialogShare.vue
@@ -143,7 +143,7 @@ export default defineComponent({
}
const { share, isSupported: shareIsSupported } = useShare();
- const { copy } = useClipboard();
+ const { copy, copied, isSupported } = useClipboard();
function getRecipeText() {
return i18n.t("recipe.share-recipe-message", [props.name]);
@@ -154,8 +154,18 @@ export default defineComponent({
}
async function copyTokenLink(token: string) {
- await copy(getTokenLink(token));
- alert.success(i18n.t("recipe-share.recipe-link-copied-message") as string);
+ if (isSupported.value) {
+ await copy(getTokenLink(token));
+ if (copied.value) {
+ alert.success(i18n.t("recipe-share.recipe-link-copied-message") as string);
+ }
+ else {
+ alert.error(i18n.t("general.clipboard-copy-failure") as string);
+ }
+ }
+ else {
+ alert.error(i18n.t("general.clipboard-not-supported") as string);
+ }
}
async function shareRecipe(token: string) {
diff --git a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPage.vue b/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPage.vue
deleted file mode 100644
index 28b96d609696..000000000000
--- a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPage.vue
+++ /dev/null
@@ -1,390 +0,0 @@
-
-
-
-
-
-
-
- {{ loadingText }}
-
-
-
-
-
-
-
-
-
-
-
-
- {{ $t("general.recipe") }}
-
-
- {{ $t("recipe.ingredients") }}
-
-
- {{ $t("recipe.instructions") }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ $t("general.new") }}
-
-
-
-
-
-
-
-
-
-
- {{ $t("general.new") }}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageCanvas.vue b/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageCanvas.vue
deleted file mode 100644
index bcba5f4fce97..000000000000
--- a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageCanvas.vue
+++ /dev/null
@@ -1,488 +0,0 @@
-
-
-
-
- {{ section.sectionTitle }}
-
-
-
-
-
- {{ icon.icon }}
-
-
-
- {{ icon.tooltip }}
-
-
-
-
-
- {{ $t("general.save") }}
-
-
- {{ $t("general.close") }}
-
-
-
-
- {{ selectedText.trim() }}
-
-
-
-
-
diff --git a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageHelp.vue b/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageHelp.vue
deleted file mode 100644
index 39ddf6e8338f..000000000000
--- a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageHelp.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
- {{ $globals.icons.help }}
-
- {{ $t("ocr-editor.help.help") }}
-
-
-
- {{ $t("ocr-editor.help.mouse-modes") }}
-
-
- {{ $globals.icons.selectMode }} {{ $t("ocr-editor.help.selection-mode") }}
-
- {{ $t("ocr-editor.help.selection-mode") }}
-
- - {{ $t("ocr-editor.help.selection-mode-steps.draw") }}
- - {{ $t("ocr-editor.help.selection-mode-steps.click") }}
- - {{ $t("ocr-editor.help.selection-mode-steps.result") }}
-
-
- {{ $globals.icons.panAndZoom }} {{ $t("ocr-editor.help.pan-and-zoom-mode") }}
-
- {{ $t("ocr-editor.help.pan-and-zoom-desc") }}
- {{ $t("ocr-editor.help.split-text-mode") }}
-
-
- {{ $globals.icons.preserveLines }}
- {{ $t("ocr-editor.help.split-modes.line-mode") }}
-
-
- {{ $t("ocr-editor.help.split-modes.line-mode-desc") }}
-
-
- {{ $globals.icons.preserveBlocks }}
- {{ $t("ocr-editor.help.split-modes.block-mode") }}
-
-
- {{ $t("ocr-editor.help.split-modes.block-mode-desc") }}
-
-
- {{ $globals.icons.flatten }} {{ $t("ocr-editor.help.split-modes.flat-mode") }}
-
- {{ $t("ocr-editor.help.split-modes.flat-mode-desc") }}
-
-
-
-
-
diff --git a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/index.ts b/frontend/components/Domain/Recipe/RecipeOcrEditorPage/index.ts
deleted file mode 100644
index ff8b655f3d15..000000000000
--- a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import RecipeOcrEditorPage from "./RecipeOcrEditorPage.vue";
-
-export default RecipeOcrEditorPage;
diff --git a/frontend/components/Domain/Recipe/RecipePage/RecipePageParts/RecipePageHeader.vue b/frontend/components/Domain/Recipe/RecipePage/RecipePageParts/RecipePageHeader.vue
index c9e4934534e0..b17cab0ca17a 100644
--- a/frontend/components/Domain/Recipe/RecipePage/RecipePageParts/RecipePageHeader.vue
+++ b/frontend/components/Domain/Recipe/RecipePage/RecipePageParts/RecipePageHeader.vue
@@ -50,7 +50,6 @@
:logged-in="isOwnGroup"
:open="isEditMode"
:recipe-id="recipe.id"
- :show-ocr-button="recipe.isOcrRecipe"
class="ml-auto mt-n8 pb-4"
@close="setMode(PageMode.VIEW)"
@json="toggleEditMode()"
@@ -58,13 +57,12 @@
@save="$emit('save')"
@delete="$emit('delete')"
@print="printRecipe"
- @ocr="goToOcrEditor"
/>
-
-
diff --git a/frontend/pages/g/_groupSlug/r/create.vue b/frontend/pages/g/_groupSlug/r/create.vue
index 72463ef0ff0f..dad973528bc1 100644
--- a/frontend/pages/g/_groupSlug/r/create.vue
+++ b/frontend/pages/g/_groupSlug/r/create.vue
@@ -52,11 +52,6 @@ export default defineComponent({
text: i18n.tc("recipe.import-with-zip"),
value: "zip",
},
- {
- icon: $globals.icons.fileImage,
- text: i18n.tc("recipe.create-recipe-from-an-image"),
- value: "ocr",
- },
{
icon: $globals.icons.link,
text: i18n.tc("recipe.bulk-url-import"),
diff --git a/frontend/pages/g/_groupSlug/r/create/ocr.vue b/frontend/pages/g/_groupSlug/r/create/ocr.vue
deleted file mode 100644
index 63acd2b61243..000000000000
--- a/frontend/pages/g/_groupSlug/r/create/ocr.vue
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
{{ $t('recipe.create-recipe-from-an-image') }}
-
- {{ $t('recipe.create-a-recipe-by-uploading-a-scan') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/frontend/types/ocr-types.ts b/frontend/types/ocr-types.ts
deleted file mode 100644
index 2b363cf239fe..000000000000
--- a/frontend/types/ocr-types.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { OcrTsvResponse } from "~/lib/api/types/ocr";
-import { Recipe } from "~/lib/api/types/recipe";
-
-export type CanvasRect = {
- startX: number;
- startY: number;
- w: number;
- h: number;
-};
-
-export type ImagePosition = {
- sx: number;
- sy: number;
- sWidth: number;
- sHeight: number;
- dx: number;
- dy: number;
- dWidth: number;
- dHeight: number;
- scale: number;
- panStartPoint: {
- x: number;
- y: number;
- };
-};
-
-export type Mouse = {
- current: {
- x: number;
- y: number;
- };
- down: boolean;
-};
-
-// https://stackoverflow.com/questions/58434389/export typescript-deep-keyof-of-a-nested-object/58436959#58436959
-type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]];
-
-type Join = K extends string | number
- ? P extends string | number
- ? `${K}${"" extends P ? "" : "."}${P}`
- : never
- : never;
-
-export type Leaves = [D] extends [never]
- ? never
- : T extends object
- ? { [K in keyof T]-?: Join> }[keyof T]
- : "";
-
-export type Paths = [D] extends [never]
- ? never
- : T extends object
- ? {
- [K in keyof T]-?: K extends string | number ? `${K}` | Join> : never;
- }[keyof T]
- : "";
-
-export type SelectedRecipeLeaves = Leaves;
-
-export type CanvasModes = "selection" | "panAndZoom";
-
-export type SelectedTextSplitModes = keyof OcrTsvResponse | "flatten";
-
-export type ToolbarIcons = {
- sectionTitle: string;
- eventHandler(mode: T): void;
- highlight: T;
- icons: {
- name: T;
- icon: string;
- tooltip: string;
- }[];
-}[];
diff --git a/mealie/lang/messages/no-NO.json b/mealie/lang/messages/no-NO.json
index 1892d68ee0ea..4fb57f87a1b2 100644
--- a/mealie/lang/messages/no-NO.json
+++ b/mealie/lang/messages/no-NO.json
@@ -11,7 +11,7 @@
"user": {
"user-updated": "Bruker oppdatert",
"password-updated": "Passord oppdatert",
- "invalid-current-password": "Feil nåværende passord",
+ "invalid-current-password": "Nåværende passord er feil",
"ldap-update-password-unavailable": "Kan ikke oppdatere passordet, brukeren kontrolleres av LDAP"
},
"group": {
@@ -29,7 +29,7 @@
"generic-updated": "{name} ble oppdatert",
"generic-created-with-url": "{name} har blitt opprettet, {url}",
"generic-updated-with-url": "{name} har blitt oppdatert, {url}",
- "generic-duplicated": "Det er blitt laget kopi av {name}",
+ "generic-duplicated": "{name} har blitt duplisert",
"generic-deleted": "{name} har blitt slettet"
}
}
diff --git a/mealie/repos/seed/resources/foods/locales/el-GR.json b/mealie/repos/seed/resources/foods/locales/el-GR.json
index eaf783db0c9f..a6c20213cef6 100644
--- a/mealie/repos/seed/resources/foods/locales/el-GR.json
+++ b/mealie/repos/seed/resources/foods/locales/el-GR.json
@@ -23,7 +23,7 @@
"broccolini": "broccolini",
"broccoli-rabe": "broccoli rabe",
"brussels-sprouts": "λαχανάκια Βρυξελλών",
- "cabbage": "cabbage",
+ "cabbage": "λάχανο",
"cauliflower": "κουνουπίδι",
"chinese-leaves": "κινέζικα φύλλα",
"collard-greens": "collard greens",
@@ -52,34 +52,34 @@
"chicory": "chicory",
"chilli-peppers": "chilli peppers",
"chives": "chives",
- "chocolate": "chocolate",
- "cilantro": "cilantro",
- "cinnamon": "cinnamon",
+ "chocolate": "σοκολάτα",
+ "cilantro": "κόλιανδρος",
+ "cinnamon": "κανέλα",
"clarified-butter": "clarified butter",
- "coconut": "coconut",
- "coconut-milk": "coconut milk",
- "coffee": "coffee",
+ "coconut": "καρύδα",
+ "coconut-milk": "γάλα καρύδας",
+ "coffee": "καφές",
"confectioners-sugar": "confectioners' sugar",
- "coriander": "coriander",
- "corn": "corn",
+ "coriander": "κόλιανδρος",
+ "corn": "καλαμπόκι",
"corn-syrup": "corn syrup",
"cottonseed-oil": "cottonseed oil",
"courgette": "courgette",
"cream-of-tartar": "cream of tartar",
- "cucumber": "cucumber",
- "cumin": "cumin",
+ "cucumber": "αγγούρι",
+ "cumin": "κύμινο",
"daikon": "daikon",
"dairy-products-and-dairy-substitutes": "dairy products and dairy substitutes",
- "eggs": "eggs",
+ "eggs": "αυγά",
"ghee": "ghee",
- "milk": "milk",
+ "milk": "γάλα",
"dandelion": "dandelion",
"demerara-sugar": "demerara sugar",
- "dough": "dough",
+ "dough": "ζυμάρι",
"edible-cactus": "edible cactus",
- "eggplant": "eggplant",
+ "eggplant": "μελιτζάνα",
"endive": "endive",
- "fats": "fats",
+ "fats": "λιπαρά",
"speck": "speck",
"fava-beans": "fava beans",
"fiddlehead": "fiddlehead",
diff --git a/mealie/repos/seed/resources/foods/locales/no-NO.json b/mealie/repos/seed/resources/foods/locales/no-NO.json
index d9fc4765b50d..ae07840f5010 100644
--- a/mealie/repos/seed/resources/foods/locales/no-NO.json
+++ b/mealie/repos/seed/resources/foods/locales/no-NO.json
@@ -36,7 +36,7 @@
"butternut-pumpkin": "flaskegresskar",
"butternut-squash": "butternut squash",
"cactus-edible": "kaktus, spiselig",
- "calabrese": "calabrese Fersk Pølse",
+ "calabrese": "calabrese",
"cannabis": "cannabis",
"capsicum": "chilipepper",
"caraway": "karve",
@@ -45,7 +45,7 @@
"cayenne-pepper": "kayenne pepper",
"celeriac": "sellerirot",
"celery": "selleri",
- "cereal-grains": "frokostblanding korn",
+ "cereal-grains": "frokostblandingkorn",
"rice": "ris",
"chard": "bladbete",
"cheese": "ost",
diff --git a/mealie/repos/seed/resources/labels/locales/el-GR.json b/mealie/repos/seed/resources/labels/locales/el-GR.json
index fe4d0175fcb7..a267bed7c74a 100644
--- a/mealie/repos/seed/resources/labels/locales/el-GR.json
+++ b/mealie/repos/seed/resources/labels/locales/el-GR.json
@@ -3,22 +3,22 @@
"name": "Produce"
},
{
- "name": "Grains"
+ "name": "Σιτηρά"
},
{
- "name": "Fruits"
+ "name": "Φρούτα"
},
{
- "name": "Vegetables"
+ "name": "Λαχανικά"
},
{
- "name": "Meat"
+ "name": "Κρέας"
},
{
- "name": "Seafood"
+ "name": "Θαλασσινά"
},
{
- "name": "Beverages"
+ "name": "Ποτά"
},
{
"name": "Baked Goods"
@@ -33,10 +33,10 @@
"name": "Confectionary"
},
{
- "name": "Dairy Products"
+ "name": "Γαλακτοκομικά"
},
{
- "name": "Frozen Foods"
+ "name": "Κατεψυγμένα Φαγητά"
},
{
"name": "Health Foods"
@@ -48,18 +48,18 @@
"name": "Meat Products"
},
{
- "name": "Snacks"
+ "name": "Σνακ"
},
{
- "name": "Spices"
+ "name": "Μπαχαρικά"
},
{
- "name": "Sweets"
+ "name": "Γλυκά"
},
{
- "name": "Alcohol"
+ "name": "Αλκοόλ"
},
{
- "name": "Other"
+ "name": "Άλλα"
}
]
diff --git a/mealie/repos/seed/resources/labels/locales/zh-CN.json b/mealie/repos/seed/resources/labels/locales/zh-CN.json
index 827b7313c627..f37e262a4b77 100644
--- a/mealie/repos/seed/resources/labels/locales/zh-CN.json
+++ b/mealie/repos/seed/resources/labels/locales/zh-CN.json
@@ -1,6 +1,6 @@
[
{
- "name": "Produce"
+ "name": "农产品"
},
{
"name": "谷物"
@@ -30,7 +30,7 @@
"name": "调味品"
},
{
- "name": "Confectionary"
+ "name": "糖果类"
},
{
"name": "乳制品"
@@ -54,7 +54,7 @@
"name": "调味品"
},
{
- "name": "甜味剂"
+ "name": "甜食"
},
{
"name": "酒类"
diff --git a/mealie/repos/seed/resources/units/locales/el-GR.json b/mealie/repos/seed/resources/units/locales/el-GR.json
index 0ef53f6336b6..bc9717fe83f4 100644
--- a/mealie/repos/seed/resources/units/locales/el-GR.json
+++ b/mealie/repos/seed/resources/units/locales/el-GR.json
@@ -2,17 +2,17 @@
"teaspoon": {
"name": "teaspoon",
"description": "",
- "abbreviation": "tsp"
+ "abbreviation": "κ.γ."
},
"tablespoon": {
"name": "tablespoon",
"description": "",
- "abbreviation": "tbsp"
+ "abbreviation": "κ.σ."
},
"cup": {
- "name": "cup",
+ "name": "φλιτζάνι",
"description": "",
- "abbreviation": "cup"
+ "abbreviation": "φλ."
},
"fluid-ounce": {
"name": "fluid ounce",
@@ -42,7 +42,7 @@
"liter": {
"name": "λίτρο",
"description": "",
- "abbreviation": "λ"
+ "abbreviation": "l"
},
"pound": {
"name": "pound",
@@ -57,17 +57,17 @@
"gram": {
"name": "γραμ",
"description": "",
- "abbreviation": "γ"
+ "abbreviation": "γρ."
},
"kilogram": {
"name": "κιλό",
"description": "",
- "abbreviation": "κιλ"
+ "abbreviation": "kg"
},
"milligram": {
"name": "χιλιοστόγραμμο",
"description": "",
- "abbreviation": "μιλιγκράμ"
+ "abbreviation": "mg"
},
"splash": {
"name": "splash",
diff --git a/mealie/repos/seed/resources/units/locales/no-NO.json b/mealie/repos/seed/resources/units/locales/no-NO.json
index b00c263bb2f8..68e74b1230b2 100644
--- a/mealie/repos/seed/resources/units/locales/no-NO.json
+++ b/mealie/repos/seed/resources/units/locales/no-NO.json
@@ -15,17 +15,17 @@
"abbreviation": "kopp"
},
"fluid-ounce": {
- "name": "us væske unse",
+ "name": "væskeunse",
"description": "",
"abbreviation": "fl oz"
},
"pint": {
- "name": "halvliter",
+ "name": "pint",
"description": "",
"abbreviation": "pt"
},
"quart": {
- "name": "quart",
+ "name": "kvart",
"description": "",
"abbreviation": "qt"
},
@@ -60,27 +60,27 @@
"abbreviation": "g"
},
"kilogram": {
- "name": "kilo",
+ "name": "kilogram",
"description": "",
"abbreviation": "kg"
},
"milligram": {
- "name": "mg",
+ "name": "milligram",
"description": "",
"abbreviation": "mg"
},
"splash": {
- "name": "splash",
+ "name": "skvett",
"description": "",
"abbreviation": ""
},
"dash": {
- "name": "dash",
+ "name": "klype",
"description": "",
"abbreviation": ""
},
"serving": {
- "name": "servering",
+ "name": "porsjon",
"description": "",
"abbreviation": ""
},
diff --git a/mealie/routes/__init__.py b/mealie/routes/__init__.py
index e421c01ae5ab..849ec5b571f9 100644
--- a/mealie/routes/__init__.py
+++ b/mealie/routes/__init__.py
@@ -7,7 +7,6 @@ from . import (
comments,
explore,
groups,
- ocr,
organizers,
parser,
recipe,
@@ -32,4 +31,3 @@ router.include_router(unit_and_foods.router)
router.include_router(admin.router)
router.include_router(validators.router)
router.include_router(explore.router)
-router.include_router(ocr.router)
diff --git a/mealie/routes/ocr/__init__.py b/mealie/routes/ocr/__init__.py
deleted file mode 100644
index e23bbc92ec8b..000000000000
--- a/mealie/routes/ocr/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from fastapi import APIRouter
-
-from . import pytesseract
-
-router = APIRouter(prefix="/ocr")
-
-router.include_router(pytesseract.router)
diff --git a/mealie/routes/ocr/pytesseract.py b/mealie/routes/ocr/pytesseract.py
deleted file mode 100644
index d2ffdec62120..000000000000
--- a/mealie/routes/ocr/pytesseract.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from fastapi import APIRouter, File
-
-from mealie.routes._base import BaseUserController, controller
-from mealie.schema.ocr.ocr import OcrAssetReq, OcrTsvResponse
-from mealie.services.ocr.pytesseract import OcrService
-from mealie.services.recipe.recipe_data_service import RecipeDataService
-from mealie.services.recipe.recipe_service import RecipeService
-
-router = APIRouter()
-
-
-@controller(router)
-class OCRController(BaseUserController):
- def __init__(self):
- self.ocr_service = OcrService()
-
- @router.post("/", response_model=str)
- def image_to_string(self, file: bytes = File(...)):
- return self.ocr_service.image_to_string(file)
-
- @router.post("/file-to-tsv", response_model=list[OcrTsvResponse])
- def file_to_tsv(self, file: bytes = File(...)):
- tsv = self.ocr_service.image_to_tsv(file)
- return self.ocr_service.format_tsv_output(tsv)
-
- @router.post("/asset-to-tsv", response_model=list[OcrTsvResponse])
- def asset_to_tsv(self, req: OcrAssetReq):
- recipe_service = RecipeService(self.repos, self.user, self.group)
- recipe = recipe_service._get_recipe(req.recipe_slug)
- if recipe.id is None:
- return []
- data_service = RecipeDataService(recipe.id, recipe.group_id)
- asset_path = data_service.dir_assets.joinpath(req.asset_name)
- file = open(asset_path, "rb")
- tsv = self.ocr_service.image_to_tsv(file.read())
-
- return self.ocr_service.format_tsv_output(tsv)
diff --git a/mealie/routes/recipe/bulk_actions.py b/mealie/routes/recipe/bulk_actions.py
index 2682564ca02f..678a157ccfb1 100644
--- a/mealie/routes/recipe/bulk_actions.py
+++ b/mealie/routes/recipe/bulk_actions.py
@@ -1,7 +1,7 @@
from functools import cached_property
from pathlib import Path
-from fastapi import APIRouter, Depends
+from fastapi import APIRouter, Depends, HTTPException
from mealie.core.dependencies.dependencies import temporary_zip_path
from mealie.core.security import create_file_token
@@ -50,6 +50,10 @@ class RecipeBulkActionsController(BaseUserController):
@router.get("/export/download")
def get_exported_data_token(self, path: Path):
"""Returns a token to download a file"""
+ path = Path(path).resolve()
+
+ if not path.is_relative_to(self.folders.DATA_DIR):
+ raise HTTPException(400, "path must be relative to data directory")
return {"fileToken": create_file_token(path)}
diff --git a/mealie/routes/recipe/recipe_crud_routes.py b/mealie/routes/recipe/recipe_crud_routes.py
index d479fe2f4ca7..caa279ea8a8a 100644
--- a/mealie/routes/recipe/recipe_crud_routes.py
+++ b/mealie/routes/recipe/recipe_crud_routes.py
@@ -27,10 +27,7 @@ from mealie.schema.make_dependable import make_dependable
from mealie.schema.recipe import Recipe, RecipeImageTypes, ScrapeRecipe
from mealie.schema.recipe.recipe import CreateRecipe, CreateRecipeByUrlBulk, RecipeLastMade, RecipeSummary
from mealie.schema.recipe.recipe_asset import RecipeAsset
-from mealie.schema.recipe.recipe_ingredient import RecipeIngredient
from mealie.schema.recipe.recipe_scraper import ScrapeRecipeTest
-from mealie.schema.recipe.recipe_settings import RecipeSettings
-from mealie.schema.recipe.recipe_step import RecipeStep
from mealie.schema.recipe.request_helpers import RecipeDuplicate, RecipeZipTokenResponse, UpdateImageResponse
from mealie.schema.response import PaginationBase, PaginationQuery
from mealie.schema.response.pagination import RecipeSearchQuery
@@ -489,37 +486,3 @@ class RecipeController(BaseRecipeController):
self.mixins.update_one(recipe, slug)
return asset_in
-
- # ==================================================================================================================
- # OCR
- @router.post("/create-ocr", status_code=201, response_model=str)
- def create_recipe_ocr(
- self, extension: str = Form(...), file: UploadFile = File(...), makefilerecipeimage: bool = Form(...)
- ):
- """Takes an image and creates a recipe based on the image"""
- slug = self.service.create_one(
- Recipe(
- name="New OCR Recipe",
- recipe_ingredient=[RecipeIngredient(note="", title=None, unit=None, food=None, original_text=None)],
- recipe_instructions=[RecipeStep(text="")],
- is_ocr_recipe=True,
- settings=RecipeSettings(show_assets=True),
- id=None,
- image=None,
- recipe_yield=None,
- rating=None,
- orgURL=None,
- date_added=None,
- date_updated=None,
- created_at=None,
- update_at=None,
- nutrition=None,
- )
- ).slug
- RecipeController.upload_recipe_asset(self, slug, "Original recipe image", "", extension, file)
- if makefilerecipeimage:
- # Get the pointer to the beginning of the file to read it once more
- file.file.seek(0)
- self.update_recipe_image(slug, file.file.read(), extension)
-
- return slug
diff --git a/mealie/routes/utility_routes.py b/mealie/routes/utility_routes.py
index 21496b2e58fc..cc67f348d375 100644
--- a/mealie/routes/utility_routes.py
+++ b/mealie/routes/utility_routes.py
@@ -3,6 +3,7 @@ from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException, status
from starlette.responses import FileResponse
+from mealie.core.config import get_app_dirs
from mealie.core.dependencies import validate_file_token
router = APIRouter(prefix="/api/utils", tags=["Utils"], include_in_schema=True)
@@ -12,6 +13,14 @@ router = APIRouter(prefix="/api/utils", tags=["Utils"], include_in_schema=True)
async def download_file(file_path: Path = Depends(validate_file_token)):
"""Uses a file token obtained by an active user to retrieve a file from the operating
system."""
+
+ file_path = Path(file_path).resolve()
+
+ dirs = get_app_dirs()
+
+ if not file_path.is_relative_to(dirs.DATA_DIR):
+ raise HTTPException(status.HTTP_400_BAD_REQUEST)
+
if not file_path.is_file():
raise HTTPException(status.HTTP_400_BAD_REQUEST)
diff --git a/mealie/schema/ocr/__init__.py b/mealie/schema/ocr/__init__.py
deleted file mode 100644
index 1c28eee01c6d..000000000000
--- a/mealie/schema/ocr/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file is auto-generated by gen_schema_exports.py
-from .ocr import OcrAssetReq, OcrTsvResponse
-
-__all__ = [
- "OcrAssetReq",
- "OcrTsvResponse",
-]
diff --git a/mealie/schema/ocr/ocr.py b/mealie/schema/ocr/ocr.py
deleted file mode 100644
index fd5351110662..000000000000
--- a/mealie/schema/ocr/ocr.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from mealie.schema._mealie import MealieModel
-
-
-class OcrTsvResponse(MealieModel):
- level: int = 0
- page_num: int = 0
- block_num: int = 0
- par_num: int = 0
- line_num: int = 0
- word_num: int = 0
- left: int = 0
- top: int = 0
- width: int = 0
- height: int = 0
- conf: float = 0.0
- text: str = ""
-
-
-class OcrAssetReq(MealieModel):
- recipe_slug: str
- asset_name: str
diff --git a/mealie/schema/recipe/recipe.py b/mealie/schema/recipe/recipe.py
index ba49e00cd071..5b5cca65aed1 100644
--- a/mealie/schema/recipe/recipe.py
+++ b/mealie/schema/recipe/recipe.py
@@ -128,7 +128,6 @@ class Recipe(RecipeSummary):
assets: list[RecipeAsset] | None = []
notes: list[RecipeNote] | None = []
extras: dict | None = {}
- is_ocr_recipe: bool | None = False
comments: list[RecipeCommentOut] | None = []
diff --git a/mealie/services/ocr/__init__.py b/mealie/services/ocr/__init__.py
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/mealie/services/ocr/pytesseract.py b/mealie/services/ocr/pytesseract.py
deleted file mode 100644
index 83d84b676b09..000000000000
--- a/mealie/services/ocr/pytesseract.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from io import BytesIO
-
-import pytesseract
-from PIL import Image
-
-from mealie.schema.ocr.ocr import OcrTsvResponse
-from mealie.services._base_service import BaseService
-
-
-class OcrService(BaseService):
- """
- Class for ocr engines.
- """
-
- def image_to_string(self, image_data):
- """
- Returns a plain text translation of an image
- """
- return pytesseract.image_to_string(Image.open(image_data))
-
- def image_to_tsv(self, image_data, lang=None):
- """
- Returns the pytesseract default tsv output
- """
- if lang is not None:
- return pytesseract.image_to_data(Image.open(BytesIO(image_data)), lang=lang)
-
- return pytesseract.image_to_data(Image.open(BytesIO(image_data)))
-
- def format_tsv_output(self, tsv: str) -> list[OcrTsvResponse]:
- """
- Returns a OcrTsvResponse from a default pytesseract tsv output
- """
- lines = tsv.split("\n")
- titles = [t.strip() for t in lines[0].split("\t")]
- response: list[OcrTsvResponse] = []
-
- for i in range(1, len(lines)):
- if lines[i] == "":
- continue
-
- line = OcrTsvResponse()
- for key, value in zip(titles, lines[i].split("\t"), strict=False):
- if key == "text":
- setattr(line, key, value.strip())
- elif key == "conf":
- setattr(line, key, float(value.strip()))
- elif key in OcrTsvResponse.__fields__:
- setattr(line, key, int(value.strip()))
- else:
- continue
-
- if isinstance(line, OcrTsvResponse):
- response.append(line)
-
- return response
diff --git a/poetry.lock b/poetry.lock
index 9bbd67e294de..f24ce60a701b 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -605,6 +605,7 @@ files = [
{file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"},
{file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"},
{file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"},
+ {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d967650d3f56af314b72df7089d96cda1083a7fc2da05b375d2bc48c82ab3f3c"},
{file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"},
{file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"},
{file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"},
@@ -613,6 +614,7 @@ files = [
{file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"},
{file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"},
{file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"},
+ {file = "greenlet-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d4606a527e30548153be1a9f155f4e283d109ffba663a15856089fb55f933e47"},
{file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"},
{file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"},
{file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"},
@@ -642,6 +644,7 @@ files = [
{file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"},
{file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"},
{file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"},
+ {file = "greenlet-2.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1087300cf9700bbf455b1b97e24db18f2f77b55302a68272c56209d5587c12d1"},
{file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"},
{file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"},
{file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"},
@@ -650,6 +653,7 @@ files = [
{file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"},
{file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"},
{file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"},
+ {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8512a0c38cfd4e66a858ddd1b17705587900dd760c6003998e9472b77b56d417"},
{file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"},
{file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"},
{file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"},
@@ -1862,21 +1866,6 @@ files = [
html5lib = "*"
rdflib = "*"
-[[package]]
-name = "pytesseract"
-version = "0.3.10"
-description = "Python-tesseract is a python wrapper for Google's Tesseract-OCR"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "pytesseract-0.3.10-py3-none-any.whl", hash = "sha256:8f22cc98f765bf13517ead0c70effedb46c153540d25783e04014f28b55a5fc6"},
- {file = "pytesseract-0.3.10.tar.gz", hash = "sha256:f1c3a8b0f07fd01a1085d451f5b8315be6eec1d5577a6796d46dc7a62bd4120f"},
-]
-
-[package.dependencies]
-packaging = ">=21.3"
-Pillow = ">=8.0.0"
-
[[package]]
name = "pytest"
version = "7.2.2"
@@ -2024,6 +2013,7 @@ files = [
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
+ {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
@@ -2031,8 +2021,15 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
+ {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
+ {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
@@ -2049,6 +2046,7 @@ files = [
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
+ {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
@@ -2056,6 +2054,7 @@ files = [
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
@@ -2205,13 +2204,13 @@ tests = ["html5lib", "pytest", "pytest-cov"]
[[package]]
name = "recipe-scrapers"
-version = "14.52.0"
+version = "14.53.0"
description = "Python package, scraping recipes from all over the internet"
optional = false
python-versions = ">=3.8"
files = [
- {file = "recipe_scrapers-14.52.0-py3-none-any.whl", hash = "sha256:3514048808c7b7de467bfa56bea3921ecff637441cde9085186345e3ce7cabdc"},
- {file = "recipe_scrapers-14.52.0.tar.gz", hash = "sha256:3d1d2cf7ad8c5fd73b5a0e921b3505daeddb42da705ef5c68523a465ccd8cd8f"},
+ {file = "recipe_scrapers-14.53.0-py3-none-any.whl", hash = "sha256:330353dc824f9d77a089e4830722fef940a04259a1a59a6578a162378ed6bc72"},
+ {file = "recipe_scrapers-14.53.0.tar.gz", hash = "sha256:916e1182fb497b89df8ac29cb816a9566aafc6d2bba73f60462aef42fc1bba22"},
]
[package.dependencies]
@@ -2972,6 +2971,16 @@ files = [
{file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"},
{file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"},
{file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"},
+ {file = "wrapt-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ecee4132c6cd2ce5308e21672015ddfed1ff975ad0ac8d27168ea82e71413f55"},
+ {file = "wrapt-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2020f391008ef874c6d9e208b24f28e31bcb85ccff4f335f15a3251d222b92d9"},
+ {file = "wrapt-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2feecf86e1f7a86517cab34ae6c2f081fd2d0dac860cb0c0ded96d799d20b335"},
+ {file = "wrapt-1.14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:240b1686f38ae665d1b15475966fe0472f78e71b1b4903c143a842659c8e4cb9"},
+ {file = "wrapt-1.14.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9008dad07d71f68487c91e96579c8567c98ca4c3881b9b113bc7b33e9fd78b8"},
+ {file = "wrapt-1.14.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6447e9f3ba72f8e2b985a1da758767698efa72723d5b59accefd716e9e8272bf"},
+ {file = "wrapt-1.14.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:acae32e13a4153809db37405f5eba5bac5fbe2e2ba61ab227926a22901051c0a"},
+ {file = "wrapt-1.14.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49ef582b7a1152ae2766557f0550a9fcbf7bbd76f43fbdc94dd3bf07cc7168be"},
+ {file = "wrapt-1.14.1-cp311-cp311-win32.whl", hash = "sha256:358fe87cc899c6bb0ddc185bf3dbfa4ba646f05b1b0b9b5a27c2cb92c2cea204"},
+ {file = "wrapt-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:26046cd03936ae745a502abf44dac702a5e6880b2b01c29aea8ddf3353b68224"},
{file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"},
{file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"},
{file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"},
@@ -3025,4 +3034,4 @@ pgsql = ["psycopg2-binary"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
-content-hash = "5e0cc403c1ec022e6a75a4969dd97c55ce312daafd7d2024a3617eca25b2129f"
+content-hash = "d7537958ae2ddbf8e2b350cb7b1189492a62b02becfe087efbc37a3b0115ff13"
diff --git a/pyproject.toml b/pyproject.toml
index 79cb8a450b50..a94c92a34dfa 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -29,7 +29,6 @@ passlib = "^1.7.4"
psycopg2-binary = { version = "^2.9.1", optional = true }
pydantic = "^1.10.4"
pyhumps = "^3.5.3"
-pytesseract = "^0.3.9"
python = "^3.10"
python-dateutil = "^2.8.2"
python-dotenv = "^1.0.0"
@@ -37,7 +36,7 @@ python-jose = "^3.3.0"
python-ldap = "^3.3.1"
python-multipart = "^0.0.6"
python-slugify = "^8.0.0"
-recipe-scrapers = "^14.52.0"
+recipe-scrapers = "^14.53.0"
requests = "^2.31.0"
tzdata = "^2022.7"
uvicorn = { extras = ["standard"], version = "^0.21.0" }
diff --git a/tests/data/images/test-ocr.png b/tests/data/images/test-ocr.png
deleted file mode 100644
index 1b699c9778d0..000000000000
Binary files a/tests/data/images/test-ocr.png and /dev/null differ
diff --git a/tests/data/text/test-ocr.tsv b/tests/data/text/test-ocr.tsv
deleted file mode 100644
index 4cb717e199d8..000000000000
--- a/tests/data/text/test-ocr.tsv
+++ /dev/null
@@ -1,73 +0,0 @@
-level page_num block_num par_num line_num word_num left top width height conf text
-1 1 0 0 0 0 0 0 640 480 -1
-2 1 1 0 0 0 36 92 582 269 -1
-3 1 1 1 0 0 36 92 582 92 -1
-4 1 1 1 1 0 36 92 544 30 -1
-5 1 1 1 1 1 36 92 60 24 87.137558 This
-5 1 1 1 1 2 109 92 20 24 87.137558 is
-5 1 1 1 1 3 141 98 15 18 87.823906 a
-5 1 1 1 1 4 169 92 32 24 87.823906 lot
-5 1 1 1 1 5 212 92 28 24 92.965874 of
-5 1 1 1 1 6 251 92 31 24 93.247513 12
-5 1 1 1 1 7 296 92 68 30 92.734741 point
-5 1 1 1 1 8 374 93 53 23 92.996040 text
-5 1 1 1 1 9 437 93 26 23 93.160057 to
-5 1 1 1 1 10 474 93 52 23 92.312637 test
-5 1 1 1 1 11 536 92 44 24 92.312637 the
-4 1 1 1 2 0 36 126 582 31 -1
-5 1 1 1 2 1 36 132 45 18 90.505524 ocr
-5 1 1 1 2 2 91 126 69 24 90.505524 code
-5 1 1 1 2 3 172 126 51 24 91.169167 and
-5 1 1 1 2 4 236 132 50 18 89.765854 see
-5 1 1 1 2 5 299 126 15 24 85.827324 if
-5 1 1 1 2 6 325 126 14 24 93.116241 it
-5 1 1 1 2 7 348 126 85 24 92.394562 works
-5 1 1 1 2 8 445 132 33 18 30.119690 on
-5 1 1 1 2 9 500 126 29 24 30.119690 all
-5 1 1 1 2 10 541 127 77 30 92.090988 types
-4 1 1 1 3 0 36 160 187 24 -1
-5 1 1 1 3 1 36 160 28 24 92.476135 of
-5 1 1 1 3 2 72 160 41 24 90.919365 file
-5 1 1 1 3 3 123 160 100 24 91.360367 format.
-3 1 1 2 0 0 36 194 561 167 -1
-4 1 1 2 1 0 36 194 549 31 -1
-5 1 1 2 1 1 36 194 55 24 89.098892 The
-5 1 1 2 1 2 102 194 75 30 89.098892 quick
-5 1 1 2 1 3 189 194 85 24 91.415680 brown
-5 1 1 2 1 4 287 194 52 31 91.943085 dog
-5 1 1 2 1 5 348 194 108 31 92.167969 jumped
-5 1 1 2 1 6 468 200 63 18 91.970985 over
-5 1 1 2 1 7 540 194 45 24 92.843704 the
-4 1 1 2 2 0 37 228 548 31 -1
-5 1 1 2 2 1 37 228 55 31 92.262550 lazy
-5 1 1 2 2 2 103 228 50 24 92.693161 fox.
-5 1 1 2 2 3 165 228 55 24 92.947639 The
-5 1 1 2 2 4 232 228 75 30 90.589806 quick
-5 1 1 2 2 5 319 228 85 24 91.051247 brown
-5 1 1 2 2 6 417 228 51 31 91.925011 dog
-5 1 1 2 2 7 478 228 107 31 91.471077 jumped
-4 1 1 2 3 0 36 262 561 31 -1
-5 1 1 2 3 1 36 268 63 18 90.210129 over
-5 1 1 2 3 2 109 262 44 24 90.210129 the
-5 1 1 2 3 3 165 262 56 31 91.178192 lazy
-5 1 1 2 3 4 231 262 50 24 92.794647 fox.
-5 1 1 2 3 5 294 262 55 24 91.388016 The
-5 1 1 2 3 6 360 262 75 30 92.525742 quick
-5 1 1 2 3 7 447 262 85 24 90.425552 brown
-5 1 1 2 3 8 545 262 52 31 90.425552 dog
-4 1 1 2 4 0 43 296 518 31 -1
-5 1 1 2 4 1 43 296 107 31 91.759590 jumped
-5 1 1 2 4 2 162 302 64 18 92.923576 over
-5 1 1 2 4 3 235 296 44 24 92.017929 the
-5 1 1 2 4 4 292 296 55 31 91.558884 lazy
-5 1 1 2 4 5 357 296 50 24 92.687485 fox.
-5 1 1 2 4 6 420 296 55 24 91.922661 The
-5 1 1 2 4 7 486 296 75 30 91.870224 quick
-4 1 1 2 5 0 37 330 524 31 -1
-5 1 1 2 5 1 37 330 85 24 92.923935 brown
-5 1 1 2 5 2 135 330 52 31 91.468765 dog
-5 1 1 2 5 3 196 330 108 31 91.425491 jumped
-5 1 1 2 5 4 316 336 63 18 91.489830 over
-5 1 1 2 5 5 388 330 45 24 91.740379 the
-5 1 1 2 5 6 445 330 55 31 92.110054 lazy
-5 1 1 2 5 7 511 330 50 24 93.180054 fox.
diff --git a/tests/data/text/test-ocr.txt b/tests/data/text/test-ocr.txt
deleted file mode 100644
index 02d3a77cbb52..000000000000
--- a/tests/data/text/test-ocr.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a lot of 12 point text to test the
-ocr code and see if it works on all types
-of file format.
-
-The quick brown dog jumped over the
-lazy fox. The quick brown dog jumped
-over the lazy fox. The quick brown dog
-jumped over the lazy fox. The quick
-brown dog jumped over the lazy fox.
diff --git a/tests/unit_tests/services_tests/test_ocr_service.py b/tests/unit_tests/services_tests/test_ocr_service.py
deleted file mode 100644
index aee3487e92b2..000000000000
--- a/tests/unit_tests/services_tests/test_ocr_service.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from pathlib import Path
-
-import pytest
-
-from mealie.services.ocr.pytesseract import OcrService
-
-ocr_service = OcrService()
-
-
-@pytest.mark.skip("Tesseract is not reliable between environments")
-def test_image_to_string():
- with open(Path("tests/data/images/test-ocr.png"), "rb") as image:
- result = ocr_service.image_to_string(image)
- with open(Path("tests/data/text/test-ocr.txt"), encoding="utf-8") as expected_result:
- assert result == expected_result.read()
-
-
-@pytest.mark.skip("Tesseract is not reliable between environments")
-def test_image_to_tsv():
- with open(Path("tests/data/images/test-ocr.png"), "rb") as image:
- result = ocr_service.image_to_tsv(image.read())
- with open(Path("tests/data/text/test-ocr.tsv"), encoding="utf-8") as expected_result:
- assert result == expected_result.read()
-
-
-def test_format_tsv_output():
- tsv = " level\tpage_num\tblock_num\tpar_num\tline_num\tword_num\tleft\ttop\twidth\theight\tconf\ttext \n1\t1\t0\t0\t0\t0\t0\t0\t640\t480\t-1\t\n5\t1\t1\t1\t1\t1\t36\t92\t60\t24\t87.137558\tThis"
- expected_result = [
- {
- "level": 1,
- "page_num": 1,
- "block_num": 0,
- "par_num": 0,
- "line_num": 0,
- "word_num": 0,
- "left": 0,
- "top": 0,
- "width": 640,
- "height": 480,
- "conf": -1.0,
- "text": "",
- },
- {
- "level": 5,
- "page_num": 1,
- "block_num": 1,
- "par_num": 1,
- "line_num": 1,
- "word_num": 1,
- "left": 36,
- "top": 92,
- "width": 60,
- "height": 24,
- "conf": 87.137558,
- "text": "This",
- },
- ]
- assert ocr_service.format_tsv_output(tsv) == expected_result
diff --git a/tests/utils/api_routes/__init__.py b/tests/utils/api_routes/__init__.py
index 1f881f198a89..de1cf2c27e90 100644
--- a/tests/utils/api_routes/__init__.py
+++ b/tests/utils/api_routes/__init__.py
@@ -113,12 +113,6 @@ groups_webhooks_rerun = "/api/groups/webhooks/rerun"
"""`/api/groups/webhooks/rerun`"""
media_docker_validate_txt = "/api/media/docker/validate.txt"
"""`/api/media/docker/validate.txt`"""
-ocr = "/api/ocr/"
-"""`/api/ocr/`"""
-ocr_asset_to_tsv = "/api/ocr/asset-to-tsv"
-"""`/api/ocr/asset-to-tsv`"""
-ocr_file_to_tsv = "/api/ocr/file-to-tsv"
-"""`/api/ocr/file-to-tsv`"""
organizers_categories = "/api/organizers/categories"
"""`/api/organizers/categories`"""
organizers_categories_empty = "/api/organizers/categories/empty"
@@ -151,8 +145,6 @@ recipes_bulk_actions_tag = "/api/recipes/bulk-actions/tag"
"""`/api/recipes/bulk-actions/tag`"""
recipes_create_from_zip = "/api/recipes/create-from-zip"
"""`/api/recipes/create-from-zip`"""
-recipes_create_ocr = "/api/recipes/create-ocr"
-"""`/api/recipes/create-ocr`"""
recipes_create_url = "/api/recipes/create-url"
"""`/api/recipes/create-url`"""
recipes_create_url_bulk = "/api/recipes/create-url/bulk"