Spaces:
Runtime error
Runtime error
Download app.py from Figmapng/cheque-bot: direct link, hf CLI and curl.
- Browser
- Download file 6.89 kB
-
https://huggingface.co/spaces/Figmapng/cheque-bot/resolve/main/app.py
- Command line
-
hf download hf://spaces/Figmapng/cheque-bot/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Figmapng/cheque-bot/resolve/main/app.py
6.89 kB
| import os | |
| import json | |
| import logging | |
| import asyncio | |
| from datetime import datetime | |
| from aiogram import Bot, Dispatcher, types | |
| from aiogram.enums import ContentType | |
| from aiogram.filters import CommandStart | |
| from google import genai | |
| from google.oauth2.service_account import Credentials | |
| from googleapiclient.discovery import build | |
| from aiohttp import web | |
| # Настройка логирования | |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
| # Токендер мен Кілттер | |
| TELEGRAM_TOKEN = os.getenv("TELEGRAM_TOKEN") | |
| GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") | |
| GOOGLE_SHEETS_ID = os.getenv("GOOGLE_SHEETS_ID") | |
| # Инициализация | |
| bot = Bot(token=TELEGRAM_TOKEN) | |
| dp = Dispatcher() | |
| ai_client = genai.Client(api_key=GEMINI_API_KEY) | |
| # Google Sheets API байланысы | |
| def append_to_sheets(rows): | |
| service_account_info = json.loads(os.getenv("GOOGLE_CREDENTIALS_JSON")) | |
| creds = Credentials.from_service_account_info( | |
| service_account_info, | |
| scopes=['https://www.googleapis.com/auth/spreadsheets'] | |
| ) | |
| service = build('sheets', 'v4', credentials=creds) | |
| sheet = service.spreadsheets() | |
| body = {'values': rows} | |
| result = sheet.values().append( | |
| spreadsheetId=GOOGLE_SHEETS_ID, | |
| range="Накладные!A2", | |
| valueInputOption="USER_ENTERED", | |
| insertDataOption="INSERT_ROWS", | |
| body=body | |
| ).execute() | |
| return result | |
| async def cmd_start(message: types.Message): | |
| await message.answer( | |
| "👋 Сәлеметсіз бе! Мен накладнойларды есепке алу ботымын.\n\n" | |
| "Маған накладнойдың немесе чектің анық түсірілген суретін жіберіңіз. " | |
| "Мен оны автоматты түрде оқып, Google Sheets кестесіне енгіземін! 📊" | |
| ) | |
| async def handle_photo(message: types.Message): | |
| status_message = await message.answer("⏳ Сурет қабылданды. Өңделуде, күте тұрыңыз...") | |
| try: | |
| # 1. Суретті Телеграмнан жүктеп алу | |
| photo = message.photo[-1] | |
| file_info = await bot.get_file(photo.file_id) | |
| photo_bytes = await bot.download_file(file_info.file_path) | |
| # 2. Суретті жаңа Gemini API-мен оқу | |
| prompt = ( | |
| "Сен накладнойларды танитын көмекшісің. Мына суреттегі накладнойды/чекті мұқият талда. " | |
| "Бұл суреттен келесі мәліметтерді тауып, тек қана валидті JSON форматында қайтар. " | |
| "Ешқандай markdown белгілерін (мысалы ```json) қоспа, тек таза JSON текст болсын. " | |
| "Егер мәлімет жоқ болса, бостой қалдыр (null немесе пустой строка). " | |
| "Формат мынадай болуы керек:\n" | |
| "{\n" | |
| " \"date\": \"Күні (КҮН.АЙ.ЖЫЛ форматында, мысалы: 23.06.2026)\",\n" | |
| " \"supplier\": \"Жіберуші/Дүкен атауы (мысалы: Строй Сити)\",\n" | |
| " \"items\": [\n" | |
| " {\n" | |
| " \"name\": \"Тауар атауы\",\n" | |
| " \"quantity\": \"Саны (өлшем бірлігімен бірге, мысалы: 10.08 м2 немесе 3 уп)\",\n" | |
| " \"price\": \"Бір бірлігінің бағасы (тек сан)\",\n" | |
| " \"total\": \"Жалпы сомасы (тек сан)\"\n" | |
| " }\n" | |
| " ]\n" | |
| "}" | |
| ) | |
| # Жаңа SDK форматында суретті жіберу | |
| response = ai_client.models.generate_content( | |
| model='gemini-1.5-flash', | |
| contents=[ | |
| genai.types.Part.from_bytes(data=photo_bytes.getvalue(), mime_type='image/jpeg'), | |
| prompt | |
| ] | |
| ) | |
| raw_text = response.text.strip() | |
| if raw_text.startswith("```json"): | |
| raw_text = raw_text[7:] | |
| if raw_text.endswith("```"): | |
| raw_text = raw_text[:-3] | |
| raw_text = raw_text.strip() | |
| data = json.loads(raw_text) | |
| date_str = data.get("date") or datetime.now().strftime("%d.%m.%Y") | |
| supplier = data.get("supplier") or "Белгісіз" | |
| items = data.get("items", []) | |
| if not items: | |
| await status_message.edit_text("❌ Суреттен тауарлар тізімі табылмады. Қайтадан анық етіп түсіріп көріңіз.") | |
| return | |
| # 3. Google Sheets жолдарын дайындау | |
| rows_to_append = [] | |
| for item in items: | |
| rows_to_append.append([ | |
| date_str, | |
| supplier, | |
| item.get("name"), | |
| item.get("quantity"), | |
| item.get("price"), | |
| item.get("total") | |
| ]) | |
| append_to_sheets(rows_to_append) | |
| report = f"✅ Накладной сәтті өңделді және Google Sheets-ке қосылды!\n\n" | |
| report += f"📅 Күні: {date_str}\n" | |
| report += f"🏪 Жіберуші: {supplier}\n" | |
| report += f"📦 Тауар саны: {len(items)} дана\n\n" | |
| report += "Таблицаңызды тексерсеңіз болады! 📈" | |
| await status_message.edit_text(report) | |
| except Exception as e: | |
| logging.error(f"Қате орын алды: {str(e)}") | |
| await status_message.edit_text("❌ Қате орын алды: Жүйе суретті тани алмады немесе Google Sheets-ке қосыла алмады.") | |
| # Render-де Port сканерлеуден өткізу үшін шағын веб-сервер | |
| async def handle_web(request): | |
| return web.Response(text="Bot is running!") | |
| async def start_web_server(): | |
| app = web.Application() | |
| app.router.add_get('/', handle_web) | |
| runner = web.AppRunner(app) | |
| await runner.setup() | |
| port = int(os.getenv("PORT", 8000)) | |
| site = web.TCPSite(runner, '0.0.0.0', port) | |
| await site.start() | |
| logging.info(f"Веб-сервер {port} портында іске қосылды.") | |
| async def main(): | |
| # Веб-сервер мен Телеграм ботты бір уақытта іске қосу | |
| await start_web_server() | |
| await dp.start_polling(bot) | |
| if __name__ == '__main__': | |
| asyncio.run(main()) |