From ddbd004633db98a94c94e8fbdf89dd5626bd1100 Mon Sep 17 00:00:00 2001 From: user Date: Sat, 1 Mar 2025 03:31:07 +0300 Subject: [PATCH] fix messages, save tonPerStar rate --- app/api/routes/content.py | 66 ++++++++++++- app/client_bot/routers/home.py | 23 ++--- app/core/background/convert_service.py | 16 ++- app/core/background/indexer_service.py | 67 ++++++++----- app/core/models/__init__.py | 2 +- locale/en/LC_MESSAGES/sanic_telegram_bot.mo | Bin 3566 -> 5660 bytes locale/en/LC_MESSAGES/sanic_telegram_bot.po | 103 ++++++++++++-------- 7 files changed, 191 insertions(+), 86 deletions(-) diff --git a/app/api/routes/content.py b/app/api/routes/content.py index 81520c6..ed7d29c 100644 --- a/app/api/routes/content.py +++ b/app/api/routes/content.py @@ -171,7 +171,7 @@ async def s_api_v1_content_friendly_list(request): with open(metadata_content.filepath, 'r') as f: metadata = json.loads(f.read()) - preview_link = 'not ready' + preview_link = None if content.meta.get('converted_content'): preview_link = f"{PROJECT_HOST}/api/v1.5/storage/{content.meta['converted_content']['low_preview']}" @@ -180,7 +180,7 @@ async def s_api_v1_content_friendly_list(request): {content.cid.serialize_v2()} {metadata.get('name', "")} {content.meta.get('item_address')} - Preview + """ + (f'Preview' if preview_link else "not ready") + """ """ result += """ @@ -189,5 +189,65 @@ async def s_api_v1_content_friendly_list(request): """ return response.html(result) - +async def s_api_v1_5_content_list(request): + # Validate offset and limit parameters + offset = int(request.args.get('offset', 0)) + limit = int(request.args.get('limit', 100)) + if offset < 0: + return response.json({'error': 'Invalid offset'}, status=400) + + if limit <= 0 or limit > 1000: + return response.json({'error': 'Invalid limit'}, status=400) + + # Query onchain contents which are not disabled + contents = request.ctx.db_session.query(StoredContent).filter( + StoredContent.type == 'onchain/content', + StoredContent.disabled == False + ).order_by(StoredContent.created.desc()).offset(offset).limit(limit).all() + + result = [] + for content in contents: + # Retrieve metadata content using metadata_cid from content.meta + metadata_cid = content.meta.get('metadata_cid') + if not metadata_cid: + continue # Skip if no metadata_cid is found + + metadata_content = StoredContent.from_cid(request.ctx.db_session, metadata_cid) + try: + with open(metadata_content.filepath, 'r') as f: + metadata = json.load(f) + except Exception as e: + metadata = {} + + media_type = 'audio' + + # Get title from metadata (key 'name') + title = metadata.get('name', '') + + # Build preview link if converted_content exists and contains 'low_preview' + preview_link = None + converted_content = content.meta.get('converted_content') + if converted_content: + converted_content = request.ctx.db_session.query(StoredContent).filter( + StoredContent.hash == converted_content['low_preview'] + ).first() + preview_link = converted_content.web_url + if converted_content.filename.split('.')[-1] in ('mp4', 'mov'): + media_type = 'video' + else: + preview_link = None + + # Get onchain address from content.meta + onchain_address = content.meta.get('item_address', '') + + result.append({ + 'cid': content.cid.serialize_v2(), + 'onchain_address': onchain_address, + 'type': media_type, + 'title': title, + 'preview_link': preview_link, + 'created_at': content.created.isoformat() # ISO 8601 format for datetime + }) + + return response.json(result) diff --git a/app/client_bot/routers/home.py b/app/client_bot/routers/home.py index a3fe36d..5e14ef4 100644 --- a/app/client_bot/routers/home.py +++ b/app/client_bot/routers/home.py @@ -14,19 +14,20 @@ main_router = Router() async def send_home_menu(chat_wrap, user, wallet_connection, **kwargs): return await tg_process_template( - chat_wrap, user.translated('home_menu').format( + chat_wrap, user.translated('clientHome_menu').format( wallet_address=Address(wallet_connection.wallet_address).to_string(1, 1, 1) if wallet_connection else user.translated('p_walletNotConnected'), name=user.front_format(plain_text=True), - ), keyboard=get_inline_keyboard([ - [{ - 'text': user.translated('ownedContent_button'), - 'callback_data': 'ownedContent' - }], - [{ - 'text': user.translated('disconnectWallet_button'), - 'callback_data': 'disconnectWallet' - }] if wallet_connection else [] - ]), **kwargs + ), # keyboard=get_inline_keyboard([ + # [{ + # 'text': user.translated('ownedContent_button'), + # 'callback_data': 'ownedContent' + # }], + # [{ + # 'text': user.translated('disconnectWallet_button'), + # 'callback_data': 'disconnectWallet' + # }] if wallet_connection else [] + # ]), + **kwargs ) diff --git a/app/core/background/convert_service.py b/app/core/background/convert_service.py index 05fa99a..6fc7a74 100644 --- a/app/core/background/convert_service.py +++ b/app/core/background/convert_service.py @@ -7,14 +7,17 @@ import shutil from base58 import b58decode, b58encode from sqlalchemy import and_, or_ from app.core.models.node_storage import StoredContent +from app.core.models._telegram import Wrapped_CBotChat from app.core._utils.send_status import send_status from app.core.logger import make_log +from app.core.models.user import User +from app.core.models import WalletConnection from app.core.storage import db_session from app.core._config import UPLOADS_DIR from app.core.content.content_id import ContentId -async def convert_loop(): +async def convert_loop(memory): with db_session() as session: # Query for unprocessed encrypted content unprocessed_encrypted_content = session.query(StoredContent).filter( @@ -193,8 +196,15 @@ async def convert_loop(): **unprocessed_encrypted_content.meta, 'converted_content': converted_content } - session.commit() + session.commit() + if not unprocessed_encrypted_content.meta.get('upload_notify_msg_id'): + wallet_owner_connection = session.query(WalletConnection).order_by(WalletConnection.id.desc()).first() + if wallet_owner_connection: + wallet_owner_user = wallet_owner_connection.user + wallet_owner_bot = Wrapped_CBotChat(memory._client_telegram_bot, chat_id=wallet_owner_user.telegram_id, user=wallet_owner_user, db_session=session) + unprocessed_encrypted_content.meta['upload_notify_msg_id'] = await wallet_owner_bot.send_content(session, unprocessed_encrypted_content) + session.commit() async def main_fn(memory): make_log("ConvertProcess", "Service started", level="info") @@ -202,7 +212,7 @@ async def main_fn(memory): while True: try: make_log("ConvertProcess", "Service running", level="debug") - await convert_loop() + await convert_loop(memory) await asyncio.sleep(5) await send_status("convert_service", f"working (seqno={seqno})") seqno += 1 diff --git a/app/core/background/indexer_service.py b/app/core/background/indexer_service.py index 378664c..fc0a9fa 100644 --- a/app/core/background/indexer_service.py +++ b/app/core/background/indexer_service.py @@ -11,7 +11,7 @@ from app.core._blockchain.ton.platform import platform from app.core._blockchain.ton.toncenter import toncenter from app.core._utils.send_status import send_status from app.core.logger import make_log -from app.core.models import UserContent, KnownTelegramMessage +from app.core.models import UserContent, KnownTelegramMessage, ServiceConfig from app.core.models.node_storage import StoredContent from app.core._utils.resolve_content import resolve_content from app.core.models.wallet_connection import WalletConnection @@ -34,6 +34,18 @@ async def indexer_loop(memory, platform_found: bool, seqno: int) -> [bool, int]: make_log("Indexer", "Service running", level="debug") with db_session() as session: + try: + result = await toncenter.run_get_method('EQD8TJ8xEWB1SpnRE4d89YO3jl0W0EiBnNS4IBaHaUmdfizE', 'get_pool_data') + assert result['exit_code'] == 0, f"Error in get-method: {result}" + assert result['stack'][0][0] == 'num', f"get first element is not num" + assert result['stack'][1][0] == 'num', f"get second element is not num" + usdt_per_ton = (int(result['stack'][0][1], 16) * 1e3) / int(result['stack'][1][1], 16) + ton_per_star = 0.014 / usdt_per_ton + await ServiceConfig(session).set('live_tonPerStar', [ton_per_star, datetime.utcnow().timestamp()]) + make_log("TON_Daemon", f"TON per STAR price: {ton_per_star}", level="DEBUG") + except BaseException as e: + make_log("TON_Daemon", f"Error while saving TON per STAR price: {e}" + '\n' + traceback.format_exc(), level="ERROR") + new_licenses = session.query(UserContent).filter( and_( ~UserContent.meta.contains({'notification_sent': True}), @@ -50,30 +62,31 @@ async def indexer_loop(memory, platform_found: bool, seqno: int) -> [bool, int]: content_metadata = licensed_content.metadata_json(session) assert content_metadata, "No content metadata found" - try: - user = new_license.user - if user.telegram_id and licensed_content: - await (Wrapped_CBotChat(memory._client_telegram_bot, chat_id=user.telegram_id, user=user, db_session=session)).send_content( - session, licensed_content - ) + if not (licensed_content.owner_address == new_license.owner_address): + try: + user = new_license.user + if user.telegram_id and licensed_content: + await (Wrapped_CBotChat(memory._client_telegram_bot, chat_id=user.telegram_id, user=user, db_session=session)).send_content( + session, licensed_content + ) - wallet_owner_connection = session.query(WalletConnection).filter_by( - wallet_address=licensed_content.owner_address, - invalidated=False - ).order_by(desc(WalletConnection.id)).first() - wallet_owner_user = wallet_owner_connection.user - if wallet_owner_user.telegram_id: - wallet_owner_bot = Wrapped_CBotChat(memory._client_telegram_bot, chat_id=wallet_owner_user.telegram_id, user=wallet_owner_user, db_session=session) - await wallet_owner_bot.send_message( - user.translated('p_licenseWasBought').format( - username=user.front_format(), - nft_address=f'"https://tonviewer.com/{new_license.onchain_address}"', - content_title=content_metadata.get('name', 'Unknown'), - ), - message_type='notification', - ) - except BaseException as e: - make_log("IndexerSendNewLicense", f"Error: {e}" + '\n' + traceback.format_exc(), level="error") + wallet_owner_connection = session.query(WalletConnection).filter_by( + wallet_address=licensed_content.owner_address, + invalidated=False + ).order_by(desc(WalletConnection.id)).first() + wallet_owner_user = wallet_owner_connection.user + if wallet_owner_user.telegram_id: + wallet_owner_bot = Wrapped_CBotChat(memory._client_telegram_bot, chat_id=wallet_owner_user.telegram_id, user=wallet_owner_user, db_session=session) + await wallet_owner_bot.send_message( + user.translated('p_licenseWasBought').format( + username=user.front_format(), + nft_address=f'"https://tonviewer.com/{new_license.onchain_address}"', + content_title=content_metadata.get('name', 'Unknown'), + ), + message_type='notification', + ) + except BaseException as e: + make_log("IndexerSendNewLicense", f"Error: {e}" + '\n' + traceback.format_exc(), level="error") new_license.meta = {**new_license.meta, 'notification_sent': True} session.commit() @@ -199,7 +212,8 @@ async def indexer_loop(memory, platform_found: bool, seqno: int) -> [bool, int]: encrypted_stored_content.user_id = user_wallet_connection.user_id user = user_wallet_connection.user - await (Wrapped_CBotChat(memory._telegram_bot, chat_id=user.telegram_id)).send_message( + user_uploader_wrapper = Wrapped_CBotChat(memory._telegram_bot, chat_id=user.telegram_id, user=user, db_session=session) + await user_uploader_wrapper.send_message( user.translated('p_contentWasIndexed').format( item_address=item_address.to_string(1, 1, 1), item_index=item_index, @@ -213,7 +227,6 @@ async def indexer_loop(memory, platform_found: bool, seqno: int) -> [bool, int]: ]) ) - user_uploader_wrapper = Wrapped_CBotChat(memory._telegram_bot, chat_id=user.telegram_id, user=user, db_session=session) for hint_message in session.query(KnownTelegramMessage).filter( and_( KnownTelegramMessage.chat_id == user.telegram_id, @@ -222,6 +235,8 @@ async def indexer_loop(memory, platform_found: bool, seqno: int) -> [bool, int]: ) ): await user_uploader_wrapper.delete_message(hint_message.message_id) + + user.client elif encrypted_stored_content.type.startswith('onchain') and encrypted_stored_content.onchain_index == item_index: encrypted_stored_content.type = "onchain/content" + ("_unknown" if (encrypted_stored_content.key_id is None) else "") encrypted_stored_content.owner_address = item_owner_address.to_string(1, 1, 1) diff --git a/app/core/models/__init__.py b/app/core/models/__init__.py index 6db8a02..475ff4f 100644 --- a/app/core/models/__init__.py +++ b/app/core/models/__init__.py @@ -8,6 +8,6 @@ from app.core.models.wallet_connection import WalletConnection from app.core.models.messages import KnownTelegramMessage from app.core.models.user_activity import UserActivity from app.core.models.content.user_content import UserContent, UserAction -from app.core.models._config import ServiceConfigValue +from app.core.models._config import ServiceConfigValue, ServiceConfig from app.core.models.asset import Asset from app.core.models.my_network import KnownNode, KnownNodeIncident, RemoteContentIndex diff --git a/locale/en/LC_MESSAGES/sanic_telegram_bot.mo b/locale/en/LC_MESSAGES/sanic_telegram_bot.mo index 0d099272c99913d5854c1e70ad6bde53ac1816e7..81897f5d7ae48d07250112c1d418c8a8e615bef6 100644 GIT binary patch literal 5660 zcmb7{Uu+y#6~?C}K(dqqDW&EAI00H{cO6Pq72}vXiIZ6PpByJ4RF$<}PwXZ3?6Nys zC$b{BHYI73I%*O~6(unusC@vWwUbRZcATIh@dVQB3#x>~g9Sne3GxC+Jn{SP%m6-$2>1HU#z`1s~!u0czcj z@Oc1~-BD2UC&4E09JmE6h40@5Kf&`~K^wgP{g(A9a4Yyxunm;m-Vl?Z_RE8x22X&G zf>%M!zZH)E7JP&p{RPze`#xw{+rWpwt>7;3_uwd4((^{k`V#nW@F}o~p!a|S;0SmL zl;0a-fxXATv*iBk;8z&`%>w}+{{o-j`LPcNaqI(6@a%${@#ml5MsO3P{EG3-IQ<~c zzXP}P{3o21pIb@Z)8GL3Cin_?n0ea>{&Ai!K$iUdCHMvK&!7W70O?-@b0NL~KEv~E zQ1kx*V#aWxJSZl8KENN;RzIKR8(RikgEoJk=TBVWs?h|djAj7I!6J2r6X{PM(o_9B z$Tw1DH1#>~li?fEW%$#hc#>AduQU*SpvZzoi_}@xP%?F7aH!yU8P^&r92>~-+?CFI zj@y+^Id0yGUZ#?6${Fh`w>wjChpoENz8sE(Lk0JUo0)KTX2!>p%p1vgnP98P-l#kY z!!h5DS8h0KXW*SPY-O?zR$Py8y}sl~b&bYN4m#cTY&NpQmd>!I<7C4zvr9IL<6tu1 z=?*(b*(W)!EDZXG3`vO9}iRA?|iS|K!}XhuPnIv zLN=Sp@h)_ZDf!W4&gn|KM?(7=Dx^|QKF>gn8-}4g6$}xvns#I{(-b9~@f7JoeFsMm}p((X5G$}*RCyzTo3cE_Ks%@ebSom{*F zu7}g^NQ?dKP}+-GD;K8zUOr>{m;IvuHh3SEehcZGVX`Kk!Tb zGE>TxS^M$HtcvltJAxaN+3+g~(B_}}u+^Eh9b@^9Oiz3ty% zt0i#3F9usIXnY9+rOH(BRWH8p-)7CN$|<}1P*W`CU+}Lp;U)RBz#u!yREfPyERy-k zOa4-2rgAd0ivzs3Lr-LX*1ok)#*Jn5I&j5({q zVje>Yt97WYxwUzy&Ax{qyARpV-<>;u{RM)Vi}HYzH`!|1FFtAF^5>NWxnNu;sFQdp z=NFlP-@G6%K^V$I+l7FK5LyK`^6+5*kzL)zBPWLkAU z$h{zP75_Xoi!Df_K5@%(lGOP(MUKDRXvv#;;TP8=T?1MTUnY7Uq=u3+0_96SX836w5-D zXlZ~DPitpUP58VM$7OVb1`;IUvedS~?q?J{4M3$%>QAut=94_}?-bOaaU*BdeOZAM z(F`Hd%}fH;W+9+t)+9a%y>dD*^0rAE;kLwDllExNIlO(#sOM$#EzQjn6BCJJnSxgs zauTV`c=JTkOO1Z>#q9&nv=2>8?8^-ec5i9(uPFKQkV<|9Pl&GSRBLmxjj*mNc$Ilm zPqm&rTICm<6AG5F6 z^5ZN4pA_8`W1~}n?8|luVwtnLgiO3mfzKwJ>nP?26lW) zTm7@hgj$Xx7^k)QBgK1?+{_E5T5D54Ci+~flqZpoS%HY&tw$pqYp76m~{ zIQ1tBc_-&4$2r+m&Z;S8(5{@&V??(($Sbe=OLi3Vq3EDv&Sv^)=H#~)OC{3Xd zwPZ7c6WTA*^4^jGikB-&*uvSRb}KQBbP2oa{CE>tndKydbF;Lr2M2X#63=8EmPD~8 z&17-*twd{c+K_pTbYREavq)C$eqnmJ$%*b5=Askzi0XCCNHMA-qy#0aT3d+#u}$1k zRpm7ktEo0~7f~DeAGfmijDK|&V=+}|NJZ6TP=m{n(#aNnNHURD*GSEdxQehL0J=_hh5w{bIN#Qapj?4~stmYnT=f?mSksj;xLj&kYF#@= zHmAa%`N}5de^y1EPnzKxgnQCV&|`HvPggr(^?>&h<4$w;p}~XB(ARckye)0q{QJ!B zeRFX8S4l;9uyEzXUqiZ)){Q2*vCe0asUD<4r^A`>`7gSskVhuY@?)*xM0G6nBmCF2 zpEsVS%$iMZYg2v^Aao=iU6EO@CV2<>!G-c|eokFi(=^<$Hv0WwE&v*i^b?)Ht9nP# zdOq|vS`~KXYKxK2FIX!-x?z5nUV(<%6-6gx^;e=_`Y*E#`+hlY(kkt(xuN{j=Au!% L4%eKh5pVqm(Q0zH literal 3566 zcmai0U5s1B6`u0jn%~kN{^9JR3aZ97MJ?-!Iwd+lkrqSx!9@{s2J#)Et zE*onVgoJniqJ%&oCVC2Al@o4czUp z>Er|8U64Ny{3-A>@W;SE09nr^;E#ZxIr$er*7GHh^?nWf3GntC()Xr;JpT=l_09o# z|6$-1Fb1;kZ@TqMz@KCO7a#$*fcF8fzfp)gfe!)MpQ6Jmko7ME?+5mQ_W)l6^8WKq z{t@tQaPv8k2d^PPUJ*Y@M)99!Qq}MK))g4<0DJ@qk%dKL}Smh=;l2!8u|7crb6b zUtAqZm58n%ceXEOT4WUIXcbE^U>3C5rxVo`JEYABhMg!;Yf7)H89f|& z*w@!ar=~J}13esjXn$Ml%I%s-U65U&LkTU)AUxCb`r~(4ZeyNT)iBJo!ldl-b~t%W znY9vTaUAsGdDWH2U?*G+QraNftCRk~KokbvNJduQF|!&*@;P6wUoCgkF3D#Ti3G5+ zoo^;8PQp+}SaZ%{OFZx*S@+eN)6b%$(~)ru!6Y{jBgLImgosrPCVZ{7TT8+~dztFi zvB}cdMn;AeSl)I>4)|TEGs(osx2>9uvPUFlv}g4N;=(V**1IQY#-4V{j=LzgE5&lLU7>?A=-|we z(bPCZhc9oQ`SeIG*9;_@0>v@__hbf=)@?_ikxuYaL8i$SAOGYXZEfiC=G(87;Ln*8 zG&}AXl-33OI7>C|7bS8ukit7X+cK`PXk#Ehw!1)$4P+(lATVxQ$Sw*~S4}h`uMZ|k zM}#98$5f1s7a8{E4dU_~`>~C>Ie!;{iw)%s<#8rt%Epk(&B;jGXwfGrtxTRq95uI* zanynCtRZ(WjE+WVYbX!$nTm5S6mq#kI(ZbD0^RS+F7d9I%1EWGY^0Q~dfhI&3+q;F zX5w!meV<+oQOEmD`MnRY4aGM z>67m5j20?iEkM!9mzgdE6_LXJj0{{M)Rv$)WeSnHp4Cf&U^JDQvjLPn8bq?UXL?{v z7?+Agv=BBeqXJS|-0+PYjwzY0?3|a2UWK$u%WX`2F1Mi9$GMth0BmqwUKKdX+O|rB zgLAWy#4@t!r=tlX4_({tl1G`d8>(lJzRcv32e}?tR$3GPyysYPUOVq1MzILVoh<6|^7SonW-xLVdd^c&X5 zWq_9I_xuiONvlFe3dfq2%b46GDzCW}sd56*~D{Qv*} diff --git a/locale/en/LC_MESSAGES/sanic_telegram_bot.po b/locale/en/LC_MESSAGES/sanic_telegram_bot.po index c1acc9f..9b2f1ef 100644 --- a/locale/en/LC_MESSAGES/sanic_telegram_bot.po +++ b/locale/en/LC_MESSAGES/sanic_telegram_bot.po @@ -21,160 +21,179 @@ msgstr "" #: app/client_bot/routers/home.py:15 app/client_bot/routers/home.py:17 msgid "home_menu" msgstr "" -"Hi, {name}! 😊\n" +"Добро пожаловать в MY! — децентрализованную систему распространения и монетизации контента!\n" "\n" -"Here you can upload your content to the blockchain and manage it 🚀.\n" +"Для загрузки контента необходимо будет подключить крипто-кошелек TON. Не бойтесь.\n" +"Нажмите «загрузить контент» и действуйте дальше интуитивно.\n" "\n" -"You're logged in as {wallet_address}" +"На всякий случай, ссылка на видеоурок по подключению кошелька здесь:\n" +"Обучающее видео\n" +"\n" +"Удачи!" + +#: Новый блок для клиента +msgid "clientHome_menu" +msgstr "" +"Добро пожаловать в плеер платформы MY!\n" +"\n" +"Здесь вы можете прослушать уже купленный контент и насладиться вашими покупками." + #: app/bot/routers/home.py:20 app/client_bot/routers/home.py:20 #: app/client_bot/routers/home.py:22 msgid "ownedContent_button" -msgstr "📊 My Content" +msgstr "📊 Мой Контент" #: app/bot/routers/home.py:24 app/client_bot/routers/home.py:24 #: app/client_bot/routers/home.py:26 msgid "disconnectWallet_button" -msgstr "🔌 Disconnect Wallet" +msgstr "🔌 Отключить кошелек" #: app/bot/routers/home.py:35 app/client_bot/routers/home.py:35 #: app/client_bot/routers/home.py:37 msgid "connectWalletsList_menu" msgstr "" -"/ Welcome to MY [🔴]\n" +"/ Добро пожаловать в MY [🔴]\n" "\n" -"Please select the wallet you want to connect to the bot 😊:" +"Пожалуйста, выберите кошелек, который вы хотите подключить к боту 😊:" #: app/bot/routers/index.py:23 app/bot/routers/index.py:22 #: app/client_bot/routers/index.py:18 app/client_bot/routers/index.py:23 msgid "error_unknownCommand" -msgstr "❌ Unknown command, please try again or press /start" +msgstr "❌ Неизвестная команда, попробуйте снова или нажмите /start" #: app/bot/routers/content.py:16 app/bot/routers/content.py:12 #: app/bot/routers/content.py:21 msgid "ownedContent_menu" msgstr "" -"📊 My Content\n" +"📊 Мой Контент\n" "\n" -"Here you can view the list of your content 📋." +"Здесь вы можете просмотреть список вашего контента 📋." #: app/bot/routers/content.py:21 app/bot/routers/content.py:17 #: app/bot/routers/content.py:47 msgid "webApp_uploadContent_button" -msgstr "📤 Upload Content" +msgstr "📤 Загрузить контент" #: app/bot/routers/content.py:27 app/bot/routers/content.py:23 #: app/bot/routers/content.py:53 app/bot/routers/content.py:68 msgid "back_button" -msgstr "◀️ Back" +msgstr "◀️ Назад" #: app/bot/routers/tonconnect.py:80 app/client_bot/routers/tonconnect.py:82 msgid "tonconnectInit_menu" -msgstr "🔌 Press the button below to connect your wallet" +msgstr "🔌 Нажмите кнопку ниже для подключения вашего кошелька" #: app/bot/routers/tonconnect.py:101 app/bot/routers/tonconnect.py:105 #: app/bot/routers/tonconnect.py:107 app/client_bot/routers/tonconnect.py:109 msgid "p_successConnectWallet" -msgstr "✅ Wallet connected successfully" +msgstr "✅ Кошелек успешно подключен" #: app/api/routes/_blockchain.py:143 app/api/routes/_blockchain.py:142 msgid "p_tonconnectTransactionRequested" msgstr "" -"⏳ Transaction requested\n" +"⏳ Запрос транзакции отправлен\n" "\n" -"👉 Please confirm the transaction in your wallet" +"👉 Пожалуйста, подтвердите транзакцию в вашем кошельке" #: app/api/routes/_blockchain.py:146 #: app/core/models/_telegram/templates/player.py:108 #: app/api/routes/_blockchain.py:145 msgid "gotoWallet_button" -msgstr "🔓 Open Wallet" +msgstr "🔓 Открыть кошелек" #: app/api/routes/_blockchain.py:150 app/bot/routers/tonconnect.py:90 #: app/core/background/indexer_service.py:141 app/bot/routers/tonconnect.py:92 #: app/core/background/indexer_service.py:156 app/api/routes/_blockchain.py:149 #: app/client_bot/routers/tonconnect.py:94 msgid "home_button" -msgstr "◀️ Back" +msgstr "◀️ Назад" #: app/bot/routers/tonconnect.py:86 app/client_bot/routers/tonconnect.py:88 msgid "tonconnectOpenWallet_button" -msgstr "[Connect Wallet]" +msgstr "[Подключить кошелек]" #: app/core/background/indexer_service.py:134 #: app/core/background/indexer_service.py:149 msgid "p_contentWasIndexed" msgstr "" -"🎉 Your new content has been uploaded successfully!\n" +"🎉 Ваш новый контент успешно загружен!\n" "\n" -"🔗 {item_address} on the blockchain\n" +"🔗 {item_address} в блокчейне\n" "\n" -"Now you can manage it in the My Content section" +"Теперь вы можете управлять им в разделе Мой Контент" #: app/core/models/_telegram/templates/player.py:74 #: app/client_bot/routers/content.py:129 msgid "shareTrack_button" -msgstr "🎶 Share Track" +msgstr "🎶 Поделиться треком" msgid "shareVideo_button" -msgstr "🎬 Share Video" +msgstr "🎬 Поделиться видео" #: app/core/models/_telegram/templates/player.py:79 msgid "viewTrackAsClient_button" -msgstr "▶️ Open in Player" +msgstr "▶️ Открыть в плеере" #: app/core/models/_telegram/templates/player.py:86 msgid "p_playerContext_unsupportedContent" -msgstr "⚠️ Unsupported Content" +msgstr "⚠️ Неподдерживаемый контент" #: app/core/models/_telegram/templates/player.py:111 msgid "p_playerContext_purchaseRequested" -msgstr "💳 Please confirm the purchase in your wallet. After that, you'll be able to listen to the full version of the track.\n\n" -"This may take a few minutes ⏳" +msgstr "💳 Пожалуйста, подтвердите покупку в вашем кошельке. После этого вы сможете прослушать полную версию трека.\n\nЭто может занять несколько минут ⏳" #: app/core/models/_telegram/templates/player.py:114 msgid "buyTrackListenLicense_button" -msgstr "💶 Buy License ({price} TON)" +msgstr "💶 Купить лицензию ({price} TON)" #: app/core/models/_telegram/templates/player.py:117 msgid "p_playerContext_preview" -msgstr "This is a preview version of the track. To listen to the full version, you need to buy a license 🎧." +msgstr "Это демонстрационная версия трека. Чтобы прослушать полную версию, необходимо приобрести лицензию 🎧." #: app/client_bot/routers/content.py:32 msgid "error_contentNotFound" -msgstr "❗ Error: Content not found" +msgstr "❗ Ошибка: Контент не найден" #: app/client_bot/routers/content.py:37 msgid "error_contentPrice" -msgstr "❗ Error: Content price is not set" +msgstr "❗ Ошибка: Цена контента не установлена" #: app/client_bot/routers/content.py:133 msgid "viewTrack_button" -msgstr "▶️ Open in Mini-App" +msgstr "▶️ Открыть в мини-приложении" #: app/client_bot/routers/content.py:138 msgid "cancelPurchase_button" -msgstr "❌ Cancel Purchase" +msgstr "❌ Отменить покупку" msgid "openContractPage_button" -msgstr "🔗 Open Smart Contract" +msgstr "🔗 Открыть смарт-контракт" msgid "noWalletConnected" -msgstr "❗ No wallet connected" +msgstr "❗ Кошелек не подключен" msgid "openTrackInApp_button" -msgstr "📱 Open in App" +msgstr "📱 Открыть в приложении" msgid "p_licenseWasBought" msgstr "" -"💶 {username} just purchased a license for {content_title}. 👏\n" -"Your content is gaining popularity! Keep creating and inspiring 🚀." +"💶 {username} только что приобрёл лицензию на {content_title}. 👏\n" +"Ваш контент набирает популярность! Продолжайте творить и вдохновлять 🚀." +#: app/api/routes/_blockchain.py:150 app/bot/routers/tonconnect.py:90 +#: app/core/background/indexer_service.py:141 app/bot/routers/tonconnect.py:92 +#: app/core/background/indexer_service.py:156 app/api/routes/_blockchain.py:149 +#: app/client_bot/routers/tonconnect.py:94 msgid "p_uploadContentTxRequested" -msgstr "⏳ Transaction for uploading {title} has been requested. Please confirm the transaction and wait for the notification. Content conversion may take up to 20 minutes." +msgstr "" +"Поздравляем! Вы успешно загрузили свой контент!\n" +"Доступ к нему появится в течение нескольких минут.\n" +"Увeдомление c загруженным контентом придет к вам в чат MY Player\n" +"Успешных продаж!" msgid "shareLink_button" -msgstr "🔗 Share Link" +msgstr "🔗 Поделиться ссылкой" msgid "p_shareLinkContext" -msgstr "🎉 Enjoy {title} on MY!" +msgstr "🎉 Наслаждайтесь {title} на MY!"