import os import sys import traceback from aiogram import types, Router, F from app.core._keyboards import get_inline_keyboard from app.core.models.node_storage import StoredContent import json from app.core.logger import make_log from app.core.models.content.user_content import UserAction from app.client_bot.routers.home import router as home_router from app.client_bot.routers.tonconnect import router as tonconnect_router from app.core._config import CLIENT_TELEGRAM_BOT_USERNAME from app.core.logger import logger from app.core.content.content_id import ContentId import base58 from datetime import datetime, timedelta import asyncio from app.core._blockchain.ton.connect import TonConnect, wallet_obj_by_name router = Router() async def t_callback_purchase_node_content(query: types.CallbackQuery, memory=None, user=None, db_session=None, chat_wrap=None, **extra): content_oid = int(query.data.split('_')[1]) is_cancel_request = query.data.split('_')[2] == 'cancel' if len(query.data.split('_')) > 2 else False content = db_session.query(StoredContent).filter_by(id=content_oid).first() if not content: return await query.answer(user.translated('error_contentNotFound'), show_alert=True) if not is_cancel_request: make_log("OwnedContent", f"{user} Try to purchase content: {content_oid}", level='info') license_price = content.meta.get('license', {}).get('listen', {}).get('price') license_price_num = int(license_price) if license_price_num < 1: return await query.answer(user.translated('error_contentPrice'), show_alert=True) ton_connect, ton_connection = TonConnect.by_user(db_session, user, callback_fn=()) await ton_connect.restore_connection() assert ton_connect.connected, "No connected wallet" user_wallet_address = user.wallet_address(db_session) memory._app.add_task(ton_connect._sdk_client.send_transaction({ 'valid_until': int(datetime.now().timestamp() + 300), 'messages': [ { 'address': content.meta['item_address'], 'amount': license_price } ] })) new_action = UserAction( type='purchase', user_id=user.id, content_id=content.id, telegram_message_id=query.message.message_id, from_address=user_wallet_address, to_address=content.meta['item_address'], status='requested', meta={ 'confirmation_url': wallet_obj_by_name(ton_connection.wallet_key.split('==')[0])['universal_url'] }, created=datetime.now() ) db_session.add(new_action) else: make_log("OwnedContent", f"{user} Try to cancel purchase: {content_oid}", level='info') action = db_session.query(UserAction).filter_by( type='purchase', content_id=content_oid, user_id=user.id, status='requested' ).first() if not action: return await query.answer() action.status = 'canceled' db_session.commit() await chat_wrap.send_content(db_session, content, message_id=query.message.message_id) router.callback_query.register(t_callback_purchase_node_content, F.data.startswith('PC_')) async def t_inline_query_node_content(query: types.InlineQuery, memory=None, user=None, db_session=None, chat_wrap=None, **extra): make_log("OwnedContent", f"Inline query: {query.query}", level='info') try: args = query.query[1:] cid = ContentId.deserialize(args) content_list = [] content = db_session.query(StoredContent).filter_by(hash=cid.content_hash_b58).first() content_prod = content.open_content(db_session) encrypted_content = content_prod['encrypted_content'] decrypted_content = content_prod['decrypted_content'] decrypted_content_meta = decrypted_content.json_format() try: metadata_content = StoredContent.from_cid(db_session, content.json_format()['metadata_cid']) with open(metadata_content.filepath, 'r') as f: metadata_content_json = json.loads(f.read()) except BaseException as e: make_log("OwnedContent", f"Can't get metadata content: {e}", level='warning') return await query.answer(content_list, cache_time=1) audio_title = metadata_content_json.get('name', "").split(' - ') title, performer = None, None if len(audio_title) > 1: performer = audio_title[0].strip() audio_title = audio_title[1:] title = audio_title[0].strip() result_kwargs = {} try: cover_content = StoredContent.from_cid(db_session, decrypted_content_meta.get('cover_cid') or None) except BaseException as e: cover_content = None if cover_content: result_kwargs['thumb_url'] = cover_content.web_url content_type_declared = decrypted_content_meta.get('content_type', 'application/x-binary').split('/')[0] content_list.append( types.InlineQueryResultAudio( id=f"NC_{content.id}", audio_url=decrypted_content.web_url + '?seconds_limit=30', title=title, performer=performer, caption=user.translated('p_playerContext_preview'), # audio_duration= parse_mode='html', reply_markup=get_inline_keyboard([ [{ 'text': { 'audio': user.translated('shareTrack_button'), 'video': user.translated('shareVideo_button'), }[content_type_declared], 'switch_inline_query': f"C{content.cid.serialize_v2()}" }], [{ 'text': user.translated('viewTrack_button'), 'url': f"https://t.me/MY_Web3Bot/content?startapp={content.cid.serialize_v2()}" }] ]), **result_kwargs ) ) return await query.answer(content_list, cache_time=1) except BaseException as e: logger.error(f"Error in t_inline_query_node_content: {e}") traceback.print_exc() return await query.answer([], cache_time=1) async def t_chosen_inline_result_node_content(query: types.ChosenInlineResult, memory=None, user=None, db_session=None, chat_wrap=None, **extra): make_log("OwnedContent", f"Chosen inline result: {query.result_id}", level='info') # return await query.answer([]) router.inline_query.register(t_inline_query_node_content, F.query.startswith('C')) router.chosen_inline_result.register(t_chosen_inline_result_node_content, lambda: True)