flaskyoutube / main.py
dxlorhuggingface's picture
Update main.py
1a15dde verified
Raw
History Blame Contribute Delete
7.93 kB
import logging
import aiohttp
import os,time
from aiohttp import FormData
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
Application, CommandHandler, MessageHandler,
filters, CallbackQueryHandler, ContextTypes
)
from dotenv import load_dotenv
load_dotenv(dotenv_path='env.env')
#config
TOKEN = "8320924107:AAH505mhHkOxeY3aLk0GObIpO_KCtY9hhLM"
API_ENDPOINT = os.getenv("API_ENDPOINT")
logging.basicConfig(level=logging.INFO)
#category mappings
VIEW_CATEGORIES = {
"crl": {
"Maxilla": "mx",
"Mandible-MDS": "mds",
"Mandible-MLS": "mls",
"Lateral ventricle": "lv",
"Head": "head",
"Gestational sac": "gsac",
"Thorax": "thorax",
"Abdomen": "ab",
"Body(Biparietal diameter)": "bd",
"Rhombencephalon": "rbp",
"Diencephalon": "dp",
"NTAPS": "ntaps",
"Nasal bone": "nb"
},
"nt": {
"Maxilla": "mx",
"Mandible-MDS": "mds",
"Mandible-MLS": "mls",
"Lateral ventricle": "lv",
"Head": "head",
"Thorax": "thorax",
"Abdomen": "ab",
"Rhombencephalon": "rbp",
"Diencephalon": "dp",
"Nuchal translucency": "nt",
"NTAPS": "ntaps",
"Nasal bone": "nb"
}
}
#start
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text("Send an ultrasound image (JPG/png only) to begin. See /instructions first")
async def instructions(update: Update, context: ContextTypes.DEFAULT_TYPE):
instruction_message = """
πŸ“‹ **Instructions**
πŸ”Έ **Step 1:** Send a cropped ultrasound image of a structure you want to analyze. See all structures with /list command
πŸ”Έ **Step 2:** Select the ultrasound view (CRL or NT)
πŸ”Έ **Step 3:** Choose the anatomical category to analyze
πŸ”Έ **Step 4:** Wait for the AI analysis results
πŸ“Œ **Important notes:**
β€’ Only JPG/PNG images are supported
β€’ Ensure the ultrasound image is clear and properly oriented
β€’ Results are for reference only - always consult a medical professional
β€’ Processing may take a few seconds
β€’ Stop bot with /stop
πŸ’‘ **Tips:**
β€’ Use high-quality, well-lit images for better accuracy
β€’ Make sure the anatomical structure is clearly visible
β€’ Different views (CRL/NT) have different category options
πŸ†˜ **Need help?** Contact support if you encounter any issues @d3ikshr.
"""
await update.message.reply_text(instruction_message, parse_mode='Markdown')
async def list_categories(update: Update, context: ContextTypes.DEFAULT_TYPE):
list_message = """
πŸ“‹ **Available Categories by View**
πŸ” **CRL view categories:**
β€’ Maxilla β€’ Mandible-MDS β€’ Mandible-MLS
β€’ Lateral ventricle β€’ Head β€’ Gestational sac
β€’ Thorax β€’ Abdomen β€’ Body(Biparietal diameter)
β€’ Rhombencephalon β€’ Diencephalon β€’ NTAPS
β€’ Nasal bone
πŸ” **NT view categories:**
β€’ Maxilla β€’ Mandible-MDS β€’ Mandible-MLS
β€’ Lateral ventricle β€’ Head β€’ Thorax
β€’ Abdomen β€’ Rhombencephalon β€’ Diencephalon
β€’ Nuchal translucency β€’ NTAPS β€’ Nasal bone
πŸ’‘ **Note:** Categories will be shown automatically based on your selected view during analysis.
"""
await update.message.reply_text(list_message, parse_mode='Markdown')
async def stop(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text("πŸ›‘ Bot stopped for this chat. Use /start to begin again.")
# Clear user data
context.user_data.clear()
# Receive image
async def handle_image(update: Update, context: ContextTypes.DEFAULT_TYPE):
photo = update.message.photo[-1]
file = await photo.get_file()
file_path = f"{update.message.from_user.id}_ultrasound.jpg"
await file.download_to_drive(file_path)
context.user_data["image_path"] = file_path
# get view
buttons = [
[InlineKeyboardButton("CRL", callback_data="view:crl"),
InlineKeyboardButton("NT", callback_data="view:nt")]
]
await update.message.reply_text(
"Select the ultrasound view:",
reply_markup=InlineKeyboardMarkup(buttons)
)
#selcet view
async def handle_view(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
view = query.data.split(":")[1]
context.user_data["selected_view"] = view
#get categories for the selected view
categories = list(VIEW_CATEGORIES[view].keys())
buttons = [[InlineKeyboardButton(cat, callback_data=f"category:{cat}")]
for cat in categories]
await query.edit_message_text(
"Select anatomical category:",
reply_markup=InlineKeyboardMarkup(buttons)
)
#get category then upload
async def handle_category(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
category_display = query.data.split(":")[1]
context.user_data["selected_category"] = category_display
image_path = context.user_data.get("image_path")
view = context.user_data.get("selected_view")
if not image_path or not view:
await query.edit_message_text("Missing image or view.")
return
await query.edit_message_text("πŸ”„ Processing image...")
time.sleep(3)
await query.edit_message_text("πŸ₯ Building diagnosis, please wait...")
try:
#read the image file into memory first
with open(image_path, "rb") as f:
image_data = f.read()
#mapping
category_value = VIEW_CATEGORIES[view][category_display]
#create form data
form = FormData()
form.add_field("view", view)
form.add_field("category", category_value)
form.add_field("source", "telegram")
form.add_field("image", image_data, filename="image.jpg", content_type="image/jpeg")
#send request
async with aiohttp.ClientSession() as session:
async with session.post(API_ENDPOINT, data=form) as resp:
if resp.status == 200:
result = await resp.json()
message = f"""
πŸ“Š **Analysis Results**
πŸ” **View:** {result.get('view', view).upper()}
πŸ₯ **Category:** {category_display}
πŸ“ˆ **Confidence:** {result.get('confidence', 0):.2f}%
⚠️ **Reconstruction error:** {result.get('error', 0):.5f}
πŸ“‹ **Status:** {result.get('comment', 'No comment')}
🩺 **Diagnosis:** {result.get('diagnosis', 'No diagnosis')}*
"""
await query.edit_message_text(message, parse_mode='Markdown')
else:
error_text = await resp.text()
await query.edit_message_text(f"❌ Upload failed. Status: {resp.status}\nError: {error_text}")
except Exception as e:
logging.error(f"Error processing request: {e}")
await query.edit_message_text(f"❌ Error: {str(e)}")
finally:
try:
if os.path.exists(image_path):
os.remove(image_path)
logging.info(f"Cleaned up image file: {image_path}")
except Exception as e:
logging.error(f"Error cleaning up file: {e}")
def main():
app = Application.builder().token(TOKEN).build()
app.add_handler(CommandHandler("start", start))
app.add_handler(CommandHandler("instructions", instructions))
app.add_handler(CommandHandler("list", list_categories))
app.add_handler(CommandHandler("stop", stop))
app.add_handler(MessageHandler(filters.PHOTO, handle_image))
app.add_handler(CallbackQueryHandler(handle_view, pattern="^view:"))
app.add_handler(CallbackQueryHandler(handle_category, pattern="^category:"))
app.run_polling()
if __name__ == "__main__":
main()