uploader-bot/app/client_bot/routers/content.py

195 lines
8.0 KiB
Python

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]
hashtags_str = (' '.join(f"#{_h}" for _h in metadata_content_json.get('hashtags', []))).strip()
if hashtags_str:
hashtags_str = hashtags_str + '\n'
if content_type_declared == 'audio':
content_list.append(
types.InlineQueryResultAudio(
id=f"NC_{content.id}",
audio_url=decrypted_content.web_url + '?seconds_limit=30',
title=title,
performer=performer,
caption=hashtags_str + user.translated('p_playerContext_preview'),
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
)
)
elif content_type_declared == 'video':
content_list.append(
types.InlineQueryResultVideo(
id=f"NC_{content.id}",
video_url=decrypted_content.web_url + '?seconds_limit=30',
title=title,
caption=hashtags_str + user.translated('p_playerContext_preview'),
parse_mode='html',
reply_markup=get_inline_keyboard([
[{
'text': user.translated('shareVideo_button'),
'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)