license_service
This commit is contained in:
parent
752f42ba02
commit
839655b163
|
|
@ -8,6 +8,7 @@ from app.core._keyboards import get_inline_keyboard
|
||||||
from app.core.models.node_storage import StoredContent
|
from app.core.models.node_storage import StoredContent
|
||||||
import json
|
import json
|
||||||
from app.core.logger import make_log
|
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.home import router as home_router
|
||||||
from app.client_bot.routers.tonconnect import router as tonconnect_router
|
from app.client_bot.routers.tonconnect import router as tonconnect_router
|
||||||
|
|
@ -15,10 +16,63 @@ from app.core._config import CLIENT_TELEGRAM_BOT_USERNAME
|
||||||
from app.core.logger import logger
|
from app.core.logger import logger
|
||||||
from app.core.content.content_id import ContentId
|
from app.core.content.content_id import ContentId
|
||||||
import base58
|
import base58
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
import asyncio
|
||||||
|
from app.core._blockchain.ton.connect import TonConnect, wallet_obj_by_name
|
||||||
|
|
||||||
|
|
||||||
router = Router()
|
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])
|
||||||
|
make_log("OwnedContent", f"{user} Try to purchase content: {content_oid}", level='info')
|
||||||
|
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)
|
||||||
|
|
||||||
|
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_at=datetime.now()
|
||||||
|
)
|
||||||
|
db_session.add(new_action)
|
||||||
|
db_session.commit()
|
||||||
|
await user.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):
|
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')
|
make_log("OwnedContent", f"Inline query: {query.query}", level='info')
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from base58 import b58encode
|
from base58 import b58encode
|
||||||
|
from sqlalchemy import and_
|
||||||
from tonsdk.boc import Cell
|
from tonsdk.boc import Cell
|
||||||
from tonsdk.utils import Address
|
from tonsdk.utils import Address
|
||||||
|
|
||||||
|
|
@ -11,11 +12,14 @@ from app.core._blockchain.ton.toncenter import toncenter
|
||||||
from app.core._utils.send_status import send_status
|
from app.core._utils.send_status import send_status
|
||||||
from app.core.logger import make_log
|
from app.core.logger import make_log
|
||||||
from app.core.models.node_storage import StoredContent
|
from app.core.models.node_storage import StoredContent
|
||||||
|
from app.core.models.content.user_content import UserContent, UserAction
|
||||||
from app.core._utils.resolve_content import resolve_content
|
from app.core._utils.resolve_content import resolve_content
|
||||||
from app.core.models.wallet_connection import WalletConnection
|
from app.core.models.wallet_connection import WalletConnection
|
||||||
from app.core._keyboards import get_inline_keyboard
|
from app.core._keyboards import get_inline_keyboard
|
||||||
from app.core.models._telegram import Wrapped_CBotChat
|
from app.core.models._telegram import Wrapped_CBotChat
|
||||||
from app.core.storage import db_session
|
from app.core.storage import db_session
|
||||||
|
from app.core._config import CLIENT_TELEGRAM_API_KEY
|
||||||
|
from app.core.models.user import User
|
||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
@ -23,7 +27,54 @@ import traceback
|
||||||
async def license_index_loop(memory, platform_found: bool, seqno: int) -> [bool, int]:
|
async def license_index_loop(memory, platform_found: bool, seqno: int) -> [bool, int]:
|
||||||
make_log("LicenseIndex", "Service running", level="debug")
|
make_log("LicenseIndex", "Service running", level="debug")
|
||||||
with db_session() as session:
|
with db_session() as session:
|
||||||
pass
|
for user in session.query(User).filter(
|
||||||
|
User.last_use > datetime.now() - timedelta(minutes=10)
|
||||||
|
).all():
|
||||||
|
try:
|
||||||
|
await user.scan_owned_user_content(session)
|
||||||
|
except BaseException as e:
|
||||||
|
make_log("LicenseIndex", f"Error: {e}" + '\n' + traceback.format_exc(), level="error")
|
||||||
|
|
||||||
|
for content in session.query(UserContent).filter(
|
||||||
|
and_(
|
||||||
|
UserContent.startswith('nft/'),
|
||||||
|
UserContent.updated < (datetime.now() - timedelta(minutes=15)),
|
||||||
|
)
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
await content.sync_with_chain(session)
|
||||||
|
except BaseException as e:
|
||||||
|
make_log("LicenseIndex", f"Error: {e}" + '\n' + traceback.format_exc(), level="error")
|
||||||
|
|
||||||
|
for action in session.query(UserAction).filter(
|
||||||
|
and_(
|
||||||
|
UserAction.type == 'purchase',
|
||||||
|
# UserAction.updated < (datetime.now() - timedelta(minutes=5)),
|
||||||
|
UserAction.status == 'requested',
|
||||||
|
)
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
user = session.query(User).filter_by(id=action.user_id).first()
|
||||||
|
chat_wrap = Wrapped_CBotChat(CLIENT_TELEGRAM_API_KEY, chat_id=user.telegram_id, db_session=session, user=user)
|
||||||
|
content = session.query(StoredContent).filter_by(id=action.content_id).first()
|
||||||
|
|
||||||
|
if (datetime.now() - action.updated) > timedelta(minutes=5):
|
||||||
|
if action.telegram_message_id:
|
||||||
|
await chat_wrap.delete_message(action.telegram_message_id)
|
||||||
|
|
||||||
|
make_log("LicenseIndex", f"Action timeout: {action.id}", level="info")
|
||||||
|
action.status = 'canceled'
|
||||||
|
else:
|
||||||
|
user_wallet_address = user.wallet_address(session)
|
||||||
|
user_content = session.query(UserContent).filter_by(content_id=action.content_id, status='active', owner_address=user_wallet_address).first()
|
||||||
|
if user_content:
|
||||||
|
make_log("LicenseIndex", f"User already has content: {user_content.content_id}", level="info")
|
||||||
|
action.status = 'success'
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
await chat_wrap.send_content(session, content)
|
||||||
|
except BaseException as e:
|
||||||
|
make_log("LicenseIndex", f"Error: {e}" + '\n' + traceback.format_exc(), level="error")
|
||||||
|
|
||||||
return platform_found, seqno
|
return platform_found, seqno
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from app.core.models.node_storage import StoredContent
|
from app.core.models.node_storage import StoredContent
|
||||||
from app.core.models.content.user_content import UserContent
|
from app.core.models.content.user_content import UserContent, UserAction
|
||||||
from app.core.logger import make_log
|
from app.core.logger import make_log
|
||||||
from app.core._utils.tg_process_template import tg_process_template
|
from app.core._utils.tg_process_template import tg_process_template
|
||||||
from app.core._config import PROJECT_HOST, CLIENT_TELEGRAM_BOT_USERNAME
|
from app.core._config import PROJECT_HOST, CLIENT_TELEGRAM_BOT_USERNAME
|
||||||
|
|
@ -96,11 +96,24 @@ class PlayerTemplates:
|
||||||
or bool(self.db_session.query(UserContent).filter_by(owner_address=user_wallet_address, status='active', content_id=content.id).first())
|
or bool(self.db_session.query(UserContent).filter_by(owner_address=user_wallet_address, status='active', content_id=content.id).first())
|
||||||
)
|
)
|
||||||
if not have_access:
|
if not have_access:
|
||||||
|
template_kwargs['audio'] = URLInputFile(local_content_url + '?seconds_limit=30')
|
||||||
|
purchase_action = self.db_session.query(UserAction).filter_by(
|
||||||
|
type='purchase',
|
||||||
|
from_address=user_wallet_address,
|
||||||
|
content_id=content.id,
|
||||||
|
status='requested'
|
||||||
|
).first()
|
||||||
|
if purchase_action:
|
||||||
|
inline_keyboard_array.append([{
|
||||||
|
'text': self.user.translated('gotoWallet_button'),
|
||||||
|
'url': purchase_action.meta['confirmation_url']
|
||||||
|
}])
|
||||||
|
text = self.user.translated('p_playerContext_purchaseRequested')
|
||||||
|
else:
|
||||||
inline_keyboard_array.append([{
|
inline_keyboard_array.append([{
|
||||||
'text': self.user.translated('buyTrackListenLicense_button').format(price=str(round(0.15, 3))),
|
'text': self.user.translated('buyTrackListenLicense_button').format(price=str(round(0.15, 3))),
|
||||||
'callback_data': f'PC_{content.id}'
|
'callback_data': f'PC_{content.id}'
|
||||||
}])
|
}])
|
||||||
template_kwargs['audio'] = URLInputFile(local_content_url + '?seconds_limit=30')
|
|
||||||
text = self.user.translated('p_playerContext_preview')
|
text = self.user.translated('p_playerContext_preview')
|
||||||
|
|
||||||
make_log("TG-Player", f"Send content {content_type} ({content_encoding}) to chat {self._chat_id}. {cd_log}")
|
make_log("TG-Player", f"Send content {content_type} ({content_encoding}) to chat {self._chat_id}. {cd_log}")
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
import base58
|
||||||
|
from sqlalchemy import and_
|
||||||
|
|
||||||
|
from app.core.logger import make_log
|
||||||
|
from app.core.models import StoredContent
|
||||||
from app.core.models.wallet_connection import WalletConnection
|
from app.core.models.wallet_connection import WalletConnection
|
||||||
from app.core._blockchain.ton.toncenter import toncenter
|
from app.core._blockchain.ton.toncenter import toncenter
|
||||||
from tonsdk.boc import Cell
|
from tonsdk.boc import Cell
|
||||||
|
|
@ -35,10 +42,44 @@ class NodeStorageIndexationMixin:
|
||||||
pass # async def fetch_onchain_metadata(self):
|
pass # async def fetch_onchain_metadata(self):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UserContentIndexationMixin:
|
class UserContentIndexationMixin:
|
||||||
pass
|
async def sync_with_chain(self, db_session):
|
||||||
|
errored = False
|
||||||
|
cc_indexator_result = await toncenter.run_get_method(self.onchain_address, 'indexator_data')
|
||||||
|
if cc_indexator_result.get('exit_code', -1) != 0:
|
||||||
|
errored = True
|
||||||
|
|
||||||
|
if not errored:
|
||||||
|
try:
|
||||||
|
cc_indexator_data = unpack_item_indexator_data(cc_indexator_result)
|
||||||
|
assert cc_indexator_data['type'] == 1, "Type is not a content"
|
||||||
|
assert cc_indexator_data['address'] == self.onchain_address, "Address is not equal"
|
||||||
|
values_slice = cc_indexator_data['values'].begin_parse()
|
||||||
|
content_hash_b58 = base58.b58encode(bytes.fromhex(values_slice.read_uint(256).hex()[2:])).decode()
|
||||||
|
stored_content = db_session.query(StoredContent).filter(
|
||||||
|
and_(
|
||||||
|
StoredContent.type == 'onchain/content',
|
||||||
|
StoredContent.hash == content_hash_b58,
|
||||||
|
|
||||||
|
)
|
||||||
|
).first()
|
||||||
|
trusted_cop_address_result = await toncenter.run_get_method(stored_content.meta['item_address'], 'get_nft_address_by_index', [['num', cc_indexator_data['index']]])
|
||||||
|
assert trusted_cop_address_result.get('exit_code', -1) == 0, "Trusted cop address error"
|
||||||
|
trusted_cop_address = Cell.one_from_boc(b64decode(trusted_cop_address_result['stack'][0][1]['bytes'])).begin_parse().read_msg_addr().to_string(1, 1, 1)
|
||||||
|
make_log("UserContent", f"Trusted cop address: {trusted_cop_address} / Contract address: {trusted_cop_address}", level="info")
|
||||||
|
assert trusted_cop_address == cc_indexator_data['address'], "Trusted cop address is not equal"
|
||||||
|
self.owner_address = cc_indexator_data['owner_address']
|
||||||
|
self.type = 'nft/listen'
|
||||||
|
self.content_id = stored_content.id
|
||||||
|
db_session.commit()
|
||||||
|
except BaseException as e:
|
||||||
|
errored = True
|
||||||
|
make_log("UserContent", f"Error: {e}" + '\n' + traceback.format_exc(), level="error")
|
||||||
|
|
||||||
|
if errored is True:
|
||||||
|
self.type = 'nft/unknown'
|
||||||
|
self.content_id = None
|
||||||
|
db_session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue