Pranesh64 commited on
Commit
a3f6574
·
verified ·
1 Parent(s): b32467e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +134 -0
app.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import json
4
+ import asyncio
5
+ import tempfile
6
+
7
+ import gradio as gr
8
+ from telethon import TelegramClient
9
+ from dotenv import load_dotenv
10
+
11
+ # ================== LOAD ENV ==================
12
+ load_dotenv()
13
+
14
+ # ================== CONFIG ==================
15
+ BOT_USERNAME = "mealschatbot"
16
+
17
+ api_id = int(os.getenv("TG_API_ID"))
18
+ api_hash = os.getenv("TG_API_HASH")
19
+ phone_number = os.getenv("TG_PHONE")
20
+
21
+ # ================== PARSER ==================
22
+ def parse_food_message(text: str):
23
+ if "Calories" not in text:
24
+ return None
25
+
26
+ data = {}
27
+
28
+ # Item name
29
+ name_match = re.search(r"You added:\s*\*\*(.+?)\*\*", text)
30
+ if name_match:
31
+ data["item"] = name_match.group(1).strip()
32
+
33
+ # Calories
34
+ cal_match = re.search(
35
+ r"\*\*Calories\*\*\s*\n+\s*(\d+)\s*kcal",
36
+ text,
37
+ re.IGNORECASE,
38
+ )
39
+ if cal_match:
40
+ data["calories_kcal"] = int(cal_match.group(1))
41
+
42
+ # Macros
43
+ macros = {}
44
+ for key, pattern in {
45
+ "protein_g": r"Protein:\s*(\d+)g",
46
+ "carbs_g": r"Carbs:\s*(\d+)g",
47
+ "fat_g": r"Fat:\s*(\d+)g",
48
+ }.items():
49
+ m = re.search(pattern, text)
50
+ if m:
51
+ macros[key] = int(m.group(1))
52
+
53
+ if macros:
54
+ data["macros"] = macros
55
+
56
+ # Ingredients
57
+ ingredients = []
58
+ block = re.search(
59
+ r"\*\*Likely Ingredients\*\*\s*\n+([\s\S]+?)(?:📊|$)",
60
+ text,
61
+ )
62
+
63
+ if block:
64
+ for line in block.group(1).splitlines():
65
+ line = line.strip("• ").strip()
66
+ if not line:
67
+ continue
68
+
69
+ m = re.match(r"(.+?)\s*\((\d+)g,\s*(\d+)kcal\)", line)
70
+ if m:
71
+ ingredients.append({
72
+ "name": m.group(1),
73
+ "quantity_g": int(m.group(2)),
74
+ "calories_kcal": int(m.group(3)),
75
+ })
76
+
77
+ if ingredients:
78
+ data["likely_ingredients"] = ingredients
79
+
80
+ return data
81
+
82
+
83
+ # ================== TELEGRAM HANDLER ==================
84
+ async def analyze_image(image_path: str):
85
+ async with TelegramClient("session", api_id, api_hash) as client:
86
+ await client.start(phone=phone_number)
87
+
88
+ bot = await client.get_entity(BOT_USERNAME)
89
+
90
+ history = await client.get_messages(bot, limit=1)
91
+ last_id_before = history[0].id if history else 0
92
+
93
+ await client.send_file(bot, image_path)
94
+ await asyncio.sleep(8)
95
+
96
+ replies = await client.get_messages(
97
+ bot,
98
+ min_id=last_id_before,
99
+ limit=10,
100
+ )
101
+
102
+ for msg in reversed(replies):
103
+ if msg.text:
104
+ parsed = parse_food_message(msg.text)
105
+ if parsed:
106
+ return parsed
107
+
108
+ return {"error": "No food data detected"}
109
+
110
+
111
+ # ================== GRADIO WRAPPER ==================
112
+ def gradio_handler(image):
113
+ with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as f:
114
+ image.save(f.name)
115
+ result = asyncio.run(analyze_image(f.name))
116
+ return json.dumps(result, indent=2)
117
+
118
+
119
+ # ================== UI ==================
120
+ with gr.Blocks(title="Meal Image → Nutrition JSON") as demo:
121
+ gr.Markdown("## 🍽️ Meal Image → Nutrition JSON")
122
+ gr.Markdown("Upload a food image. Output will be **pure JSON only**.")
123
+
124
+ image_input = gr.Image(type="pil", label="Upload Food Image")
125
+ json_output = gr.Code(label="Parsed JSON", language="json")
126
+
127
+ analyze_btn = gr.Button("Analyze")
128
+ analyze_btn.click(
129
+ fn=gradio_handler,
130
+ inputs=image_input,
131
+ outputs=json_output,
132
+ )
133
+
134
+ demo.launch()