diff --git a/app/__main__.py b/app/__main__.py index 03d0918..ecd1a8b 100644 --- a/app/__main__.py +++ b/app/__main__.py @@ -67,8 +67,9 @@ if __name__ == '__main__': except BaseException: pass + main_memory = Memory() if startup_target == '__main__': - app.ctx.memory = Memory() + app.ctx.memory = main_memory for _target in [uploader_bot_dp, client_bot_dp]: _target._s_memory = app.ctx.memory @@ -94,9 +95,9 @@ if __name__ == '__main__': startup_fn = startup_fn or target_fn assert startup_fn - async def wrapped_startup_fn(): + async def wrapped_startup_fn(*args): try: - await startup_fn() + await startup_fn(*args) except BaseException as e: make_log(startup_target[0].upper() + startup_target[1:], f"Error: {e}" + '\n' + str(traceback.format_exc()), level='error') @@ -104,7 +105,7 @@ if __name__ == '__main__': loop = asyncio.get_event_loop() try: - loop.run_until_complete(wrapped_startup_fn()) + loop.run_until_complete(wrapped_startup_fn(main_memory)) except BaseException as e: make_log(startup_target[0].upper() + startup_target[1:], f"Error: {e}" + '\n' + str(traceback.format_exc()), level='error') diff --git a/app/core/background/indexer_service.py b/app/core/background/indexer_service.py index 8bf5788..8e8ffe8 100644 --- a/app/core/background/indexer_service.py +++ b/app/core/background/indexer_service.py @@ -12,12 +12,14 @@ from app.core._utils.send_status import send_status from app.core.logger import make_log from app.core.models.node_storage import StoredContent from app.core.models.wallet_connection import WalletConnection +from app.core._keyboards import get_inline_keyboard +from app.core.models._telegram import Wrapped_CBotChat from app.core.storage import db_session import os import traceback -async def indexer_loop(platform_found: bool, seqno: int) -> [bool, int]: +async def indexer_loop(memory, platform_found: bool, seqno: int) -> [bool, int]: if not platform_found: platform_state = await toncenter.get_account(platform.address.to_string(1, 1, 1)) if not platform_state.get('code'): @@ -120,14 +122,29 @@ async def indexer_loop(platform_found: bool, seqno: int) -> [bool, int]: and encrypted_stored_content.onchain_index != item_index if not is_duplicate: if encrypted_stored_content.type.startswith('local'): - encrypted_stored_content.type = "onchain/content" + ( - "_unknown" if not (encrypted_stored_content.key_id is None) else "") + encrypted_stored_content.type = "onchain/content" + ("_unknown" if (encrypted_stored_content.key_id is None) else "") encrypted_stored_content.onchain_index = item_index encrypted_stored_content.owner_address = item_owner_address.to_string(1, 1, 1) + user = None if user_wallet_connection: 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.translated('p_contentWasIndexed').format( + item_address=item_address.to_string(1, 1, 1), + item_index=item_index, + ), + message_type='notification', + reply_markup=get_inline_keyboard([ + [{ + 'text': user.translated('home_button'), + 'callback_data': 'home' + }] + ]) + ) elif encrypted_stored_content.type.startswith('onchain') and encrypted_stored_content.onchain_index == item_index: - encrypted_stored_content.type = "onchain/content" + ("_unknown" if not (encrypted_stored_content.key_id is None) else "") + 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) if user_wallet_connection: encrypted_stored_content.user_id = user_wallet_connection.user_id @@ -168,13 +185,13 @@ async def indexer_loop(platform_found: bool, seqno: int) -> [bool, int]: return platform_found, seqno -async def main_fn(): +async def main_fn(memory, ): make_log("Indexer", "Service started", level="info") platform_found = False seqno = 0 while True: try: - platform_found, seqno = await indexer_loop(platform_found, seqno) + platform_found, seqno = await indexer_loop(memory, platform_found, seqno) except BaseException as e: make_log("Indexer", f"Error: {e}" + '\n' + traceback.format_exc(), level="error") diff --git a/app/core/background/ton_service.py b/app/core/background/ton_service.py index d0b4f3e..40e4082 100644 --- a/app/core/background/ton_service.py +++ b/app/core/background/ton_service.py @@ -21,7 +21,7 @@ async def get_sw_seqno(): return sw_seqno_value -async def main_fn(): +async def main_fn(memory): make_log("TON", f"Service started, SW = {service_wallet.address.to_string(1, 1, 1)}", level="info") sw_seqno_value = await get_sw_seqno() make_log("TON", f"Service wallet run seqno method: {sw_seqno_value}", level="info") diff --git a/app/core/background/uploader_service.py b/app/core/background/uploader_service.py index e42b76a..d1c1303 100644 --- a/app/core/background/uploader_service.py +++ b/app/core/background/uploader_service.py @@ -8,7 +8,7 @@ async def uploader_loop(): pass -async def main_fn(): +async def main_fn(memory): make_log("Uploader", "Service started", level="info") seqno = 0 while True: diff --git a/app/core/content/content_id.py b/app/core/content/content_id.py index de02a61..75a485f 100644 --- a/app/core/content/content_id.py +++ b/app/core/content/content_id.py @@ -17,7 +17,7 @@ class ContentId: version: int = None, content_hash: bytes = None, # only SHA256 onchain_index: int = None, - accept_type: str = 'image/jpeg', + accept_type: str = None, encryption_key_sha256: bytes = None, ): self.version = version diff --git a/app/core/models/__init__.py b/app/core/models/__init__.py index 0118e95..2a827e1 100644 --- a/app/core/models/__init__.py +++ b/app/core/models/__init__.py @@ -6,3 +6,4 @@ from app.core.models.node_storage import StoredContent from app.core.models.transaction import UserBalance, InternalTransaction from app.core.models.user import User from app.core.models.wallet_connection import WalletConnection +from app.core.models.messages import KnownTelegramMessage diff --git a/app/core/models/_telegram/wrapped_bot.py b/app/core/models/_telegram/wrapped_bot.py index 485cad1..7ccf7d3 100644 --- a/app/core/models/_telegram/wrapped_bot.py +++ b/app/core/models/_telegram/wrapped_bot.py @@ -1,10 +1,12 @@ -from aiogram import Bot +from aiogram import Bot, types +from datetime import datetime, timedelta from app.core.logger import make_log +from app.core.models.messages import KnownTelegramMessage class Wrapped_CBotChat: - def __init__(self, api_key: str, chat_id: int = None, **kwargs): + def __init__(self, api_key: str, chat_id: int = None, db_session=None, **kwargs): if isinstance(api_key, Bot): self._bot_key = api_key.token self._bot = api_key @@ -15,6 +17,7 @@ class Wrapped_CBotChat: raise TypeError(f'api_key must be Bot or str, not {type(api_key)}') self._chat_id = chat_id + self.db_session = db_session self.options = kwargs def __repr__(self): @@ -23,16 +26,46 @@ class Wrapped_CBotChat: return "Bot" - async def send_message(self, text: str, **kwargs): + async def return_result(self, result, message_type='common'): + if message_type == 'common': + ci = 0 + for oc_msg in self.db_session.query(KnownTelegramMessage).filter( + KnownTelegramMessage.type == 'common', + KnownTelegramMessage.chat_id == self._chat_id, + ).all(): + await self.delete_message(oc_msg.message_id) + ci += 1 + + make_log(self, f"Deleted {ci} old messages", level='debug') + + if isinstance(result, types.Message): + message_id = getattr(result, 'message_id', None) + assert message_id, "No message_id" + self.db_session.add( + KnownTelegramMessage( + type=message_type, + chat_id=self._chat_id, + message_id=message_id, + created=datetime.now() + ) + ) + self.db_session.commit() + else: + make_log(self, f"Unknown result type: {type(result)}", level='warning') + + return result + + async def send_message(self, text: str, message_type='common', **kwargs): try: make_log(self, f"Send message to {self._chat_id}. Text len: {len(text)}", level='debug') - return await self._bot.send_message( + r = await self._bot.send_message( self._chat_id, text, parse_mode='html', disable_web_page_preview=True, **kwargs ) + return await self.return_result(r, message_type=message_type) except BaseException as e: make_log(self, f"Error sending message to {self._chat_id}. Error: {e}", level='warning') return None @@ -48,6 +81,7 @@ class Wrapped_CBotChat: disable_web_page_preview=True, **kwargs ) + except Exception as e: make_log(self, f"Error editing message {self._chat_id}/{message_id}. Error: {e}", level='warning') if 'exactly the same as a current content' in f'{e}': @@ -66,64 +100,69 @@ class Wrapped_CBotChat: make_log(self, f"Error deleting message {self._chat_id}/{message_id}. Error: {e}", level='warning') return None - async def send_photo(self, file_id, **kwargs): + async def send_photo(self, file_id, message_type='common', **kwargs): try: make_log(self, f"Send photo to {self._chat_id}. File: {file_id}", level='debug') - return await self._bot.send_photo( + r = await self._bot.send_photo( self._chat_id, file_id, **kwargs ) + return await self.return_result(r, message_type=message_type) except Exception as e: make_log(self, f"Error sending photo to {self._chat_id}. Error: {e}", level='warning') return None - async def send_document(self, file_id, **kwargs): + async def send_document(self, file_id, message_type='common', **kwargs): try: make_log(self, f"Send document to {self._chat_id}. File: {file_id}", level='debug') - return await self._bot.send_document( + r = await self._bot.send_document( self._chat_id, file_id, **kwargs ) + return await self.return_result(r, message_type=message_type) except Exception as e: make_log(self, f"Error sending document to {self._chat_id}. Error: {e}", level='warning') return None - async def send_video(self, file_id, **kwargs): + async def send_video(self, file_id, message_type='common', **kwargs): try: make_log(self, f"Send video to {self._chat_id}. File: {file_id}", level='debug') - return await self._bot.send_video( + r = await self._bot.send_video( self._chat_id, file_id, **kwargs ) + return await self.return_result(r, message_type=message_type) except Exception as e: make_log(self, f"Error sending video to {self._chat_id}. Error: {e}", level='warning') return None - async def copy_message(self, from_chat_id, message_id, **kwargs): + async def copy_message(self, from_chat_id, message_id, message_type='common', **kwargs): try: make_log(self, f"Copy message from {from_chat_id}/{message_id} to {self._chat_id}", level='debug') - return await self._bot.copy_message( + r = await self._bot.copy_message( self._chat_id, from_chat_id, message_id, **kwargs ) + return await self.return_result(r, message_type=message_type) except Exception as e: make_log(self, f"Error copying message from {from_chat_id}/{message_id} to {self._chat_id}. Error: {e}", level='warning') return None - async def forward_message(self, from_chat_id, message_id, **kwargs): + async def forward_message(self, from_chat_id, message_id, message_type='common', **kwargs): try: make_log(self, f"Forward message from {from_chat_id}/{message_id} to {self._chat_id}", level='debug') - return await self._bot.forward_message( + r = await self._bot.forward_message( self._chat_id, from_chat_id, message_id, **kwargs ) + return await self.return_result(r, message_type=message_type) except Exception as e: make_log(self, f"Error forwarding message from {from_chat_id}/{message_id} to {self._chat_id}. Error: {e}", level='warning') return None diff --git a/app/core/models/messages.py b/app/core/models/messages.py new file mode 100644 index 0000000..058bebc --- /dev/null +++ b/app/core/models/messages.py @@ -0,0 +1,17 @@ +from base58 import b58decode +from sqlalchemy import Column, Integer, String, DateTime, JSON, BigInteger + +from .base import AlchemyBase + + +# Only for clean old messages now + + +class KnownTelegramMessage(AlchemyBase): + __tablename__ = 'known_telegram_messages' + + id = Column(Integer, autoincrement=True, primary_key=True) + type = Column(String(64), nullable=True) + chat_id = Column(BigInteger, nullable=False) + message_id = Column(BigInteger, nullable=False) + created = Column(DateTime, nullable=False, default=0) diff --git a/locale/en/LC_MESSAGES/sanic_telegram_bot.mo b/locale/en/LC_MESSAGES/sanic_telegram_bot.mo index 3adafa5..bc58acb 100644 Binary files a/locale/en/LC_MESSAGES/sanic_telegram_bot.mo and b/locale/en/LC_MESSAGES/sanic_telegram_bot.mo differ diff --git a/locale/en/LC_MESSAGES/sanic_telegram_bot.po b/locale/en/LC_MESSAGES/sanic_telegram_bot.po index c11056b..6c113fd 100644 --- a/locale/en/LC_MESSAGES/sanic_telegram_bot.po +++ b/locale/en/LC_MESSAGES/sanic_telegram_bot.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-03-08 22:45+0300\n" +"POT-Creation-Date: 2024-03-10 12:02+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -64,25 +64,37 @@ msgstr "ā—€ļø Back" #: app/bot/routers/tonconnect.py:80 msgid "tonconnectInit_menu" -msgstr "" -"šŸ”Œ Press the button below to connect your wallet" +msgstr "šŸ”Œ Press the button below to connect your wallet" #: app/bot/routers/tonconnect.py:101 app/bot/routers/tonconnect.py:105 +#: app/bot/routers/tonconnect.py:107 msgid "p_successConnectWallet" msgstr "āœ… Wallet connected successfully" #: app/api/routes/_blockchain.py:143 msgid "p_tonconnectTransactionRequested" -msgstr "ā³ Transaction requested\n\nšŸ‘‰ Please confirm the transaction in your wallet" +msgstr "" +"ā³ Transaction requested\n" +"\n" +"šŸ‘‰ Please confirm the transaction in your wallet" #: app/api/routes/_blockchain.py:146 msgid "gotoWallet_button" msgstr "Open wallet" #: 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 msgid "home_button" msgstr "ā—€ļø Back" #: app/bot/routers/tonconnect.py:86 msgid "tonconnectOpenWallet_button" msgstr "[Connect wallet]" + +#: app/core/background/indexer_service.py:134 +msgid "p_contentWasIndexed" +msgstr "šŸŽ‰ Your new content was uploaded successfully!" +"\n\n" +"šŸ”— {item_address} on the blockchain" +"\n\n" +"Now you can manage it in My content section"