├── .gitignore ├── CHANGELOG.md ├── Config.py ├── LICENSE ├── README.md ├── balebot ├── __init__.py ├── __version__.py ├── bale_future.py ├── bot.py ├── config.py ├── connection │ ├── __init__.py │ └── network.py ├── dispatcher.py ├── filters │ ├── __init__.py │ ├── bank_message_filter.py │ ├── contact_filter.py │ ├── default.py │ ├── document_filter.py │ ├── filter.py │ ├── json_filter.py │ ├── location_filter.py │ ├── photo_filter.py │ ├── sticker_filter.py │ ├── template_message_filter.py │ ├── template_response_filter.py │ ├── text_filter.py │ ├── unsupported_filter.py │ ├── video_filter.py │ └── voice_filter.py ├── handlers │ ├── __init__.py │ ├── command_handler.py │ ├── handler.py │ ├── message_handler.py │ └── quoted_message_handler.py ├── models │ ├── __init__.py │ ├── base_models │ │ ├── __init__.py │ │ ├── avatar.py │ │ ├── banking │ │ │ ├── __init__.py │ │ │ ├── bank_account.py │ │ │ ├── bank_ext.py │ │ │ ├── deprecated_receipt.py │ │ │ ├── deprecated_receipt_message.py │ │ │ └── receipt_message.py │ │ ├── bot_api_quoted_message.py │ │ ├── bot_command.py │ │ ├── bot_quoted_message.py │ │ ├── contact.py │ │ ├── contact_record.py │ │ ├── fat_seq_update.py │ │ ├── file_location.py │ │ ├── group.py │ │ ├── group_member.py │ │ ├── group_peer.py │ │ ├── image_location.py │ │ ├── jsonable.py │ │ ├── member.py │ │ ├── pack_info.py │ │ ├── peer.py │ │ ├── raw_json.py │ │ ├── request.py │ │ ├── request_body.py │ │ ├── response.py │ │ ├── response_body.py │ │ ├── user.py │ │ ├── user_peer.py │ │ └── value_types │ │ │ ├── __init__.py │ │ │ ├── array_val.py │ │ │ ├── boolean_value.py │ │ │ ├── double_val.py │ │ │ ├── int32_val.py │ │ │ ├── int64_val.py │ │ │ ├── map_value.py │ │ │ ├── map_value_item.py │ │ │ ├── raw_value.py │ │ │ └── string_val.py │ ├── client_requests │ │ ├── __init__.py │ │ ├── files │ │ │ ├── __init__.py │ │ │ ├── get_file_download_url.py │ │ │ └── get_file_upload_url.py │ │ ├── group │ │ │ ├── __init__.py │ │ │ ├── create_group.py │ │ │ ├── get_group_api_struct.py │ │ │ └── invite_user.py │ │ ├── messaging │ │ │ ├── __init__.py │ │ │ ├── edit_message.py │ │ │ └── send_message.py │ │ └── sequence │ │ │ ├── __init__.py │ │ │ ├── get_difference.py │ │ │ └── get_last_sequence.py │ ├── constants │ │ ├── __init__.py │ │ ├── bank_ext_types.py │ │ ├── default_purchase_message_photo.py │ │ ├── document_type.py │ │ ├── errors.py │ │ ├── file_type.py │ │ ├── message_type.py │ │ ├── peer_type.py │ │ ├── raw_json_type.py │ │ ├── receipt_type.py │ │ ├── request_to_response_mapper.py │ │ ├── request_type.py │ │ ├── service_type.py │ │ ├── template_button_action_type.py │ │ ├── update_body_type.py │ │ └── value_type.py │ ├── factories │ │ ├── __init__.py │ │ ├── bank_ext_factory.py │ │ ├── message_factory.py │ │ ├── raw_json_factory.py │ │ ├── raw_value_factory.py │ │ ├── server_update_factory.py │ │ └── update_body_factory.py │ ├── messages │ │ ├── __init__.py │ │ ├── banking │ │ │ ├── __init__.py │ │ │ ├── bank_message.py │ │ │ ├── money_request_type.py │ │ │ └── purchase_message.py │ │ ├── base_message.py │ │ ├── contact_message.py │ │ ├── document_message.py │ │ ├── json_message.py │ │ ├── location_message.py │ │ ├── photo_message.py │ │ ├── sticker_message.py │ │ ├── template │ │ │ ├── __init__.py │ │ │ ├── template_message.py │ │ │ └── template_message_button.py │ │ ├── template_response_message.py │ │ ├── text_message.py │ │ ├── unsupported_message.py │ │ ├── video_message.py │ │ └── voice_message.py │ ├── server_responses │ │ ├── __init__.py │ │ ├── bot_error_response.py │ │ ├── bot_success_response.py │ │ ├── files │ │ │ ├── __init__.py │ │ │ ├── response_get_download_url.py │ │ │ └── response_get_upload_url.py │ │ ├── group │ │ │ ├── __init__.py │ │ │ ├── get_group_api_response.py │ │ │ └── response_create_group.py │ │ ├── messaging │ │ │ ├── __init__.py │ │ │ ├── message_edited.py │ │ │ └── message_sent.py │ │ └── sequence │ │ │ ├── __init__.py │ │ │ ├── difference_update.py │ │ │ └── get_last_seq_response.py │ └── server_updates │ │ ├── __init__.py │ │ ├── bot_read_update_body.py │ │ ├── bot_received_update_body.py │ │ ├── message_update_body.py │ │ ├── raw_update_body.py │ │ └── update_body.py ├── updater.py └── utils │ ├── __init__.py │ ├── logger.py │ └── util_functions.py ├── examples ├── assets │ ├── happy-bot.jpeg │ ├── image_3200.png │ ├── image_3370.png │ ├── image_6450.png │ ├── image_7450.png │ ├── image_7890.png │ └── image_9390.png ├── bank_receipt_conversation.py ├── contact_conversation.py ├── document_conversation.py ├── echobot.py ├── location_conversation.py ├── photo_voice_conversation.py ├── purchase_conversation.py ├── quoted_message_conversation.py ├── simple_edit_message.py ├── template_message_conversation.py └── text_conversation.py ├── requirements.txt ├── setup.py └── test_bale_bot ├── __init__.py ├── test_bot.py └── test_models ├── __init__.py ├── test_client_requests ├── __init__.py └── test_messaging │ ├── __init__.py │ └── test_edit_message.py └── test_resver_responses ├── __init__.py └── test_messaging ├── __init__.py └── test_message_edited.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 5 | 6 | # User-specific stuff: 7 | .idea/**/workspace.xml 8 | .idea/**/tasks.xml 9 | .idea/dictionaries 10 | 11 | # Sensitive or high-churn files: 12 | .idea/**/dataSources/ 13 | .idea/**/dataSources.ids 14 | .idea/**/dataSources.xml 15 | .idea/**/dataSources.local.xml 16 | .idea/**/sqlDataSources.xml 17 | .idea/**/dynamic.xml 18 | .idea/**/uiDesigner.xml 19 | 20 | # Gradle: 21 | .idea/**/gradle.xml 22 | .idea/**/libraries 23 | 24 | # Mongo Explorer plugin: 25 | .idea/**/mongoSettings.xml 26 | 27 | ## File-based project format: 28 | *.iws 29 | 30 | ## Plugin-specific files: 31 | 32 | # IntelliJ 33 | /out/ 34 | 35 | # mpeltonen/sbt-idea plugin 36 | .idea_modules/ 37 | 38 | # JIRA plugin 39 | atlassian-ide-plugin.xml 40 | 41 | # Crashlytics plugin (for Android Studio and IntelliJ) 42 | com_crashlytics_export_strings.xml 43 | crashlytics.properties 44 | crashlytics-build.properties 45 | fabric.properties 46 | ### VirtualEnv template 47 | # Virtualenv 48 | # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ 49 | .Python 50 | [Bb]in 51 | [Ii]nclude 52 | [Ll]ib 53 | [Ll]ib64 54 | [Ll]ocal 55 | [Ss]cripts 56 | pyvenv.cfg 57 | .venv 58 | pip-selfcheck.json 59 | ### Python template 60 | # Byte-compiled / optimized / DLL files 61 | __pycache__/ 62 | *.py[cod] 63 | *$py.class 64 | 65 | # C extensions 66 | *.so 67 | 68 | # Distribution / packaging 69 | .Python 70 | env/ 71 | build/ 72 | develop-eggs/ 73 | dist/ 74 | downloads/ 75 | eggs/ 76 | .eggs/ 77 | lib/ 78 | lib64/ 79 | parts/ 80 | sdist/ 81 | var/ 82 | wheels/ 83 | *.egg-info/ 84 | .installed.cfg 85 | *.egg 86 | 87 | # PyInstaller 88 | # Usually these files are written by a python script from a template 89 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 90 | *.manifest 91 | *.spec 92 | 93 | # Installer logs 94 | pip-log.txt 95 | pip-delete-this-directory.txt 96 | 97 | # Unit test / coverage reports 98 | htmlcov/ 99 | .tox/ 100 | .coverage 101 | .coverage.* 102 | .cache 103 | nosetests.xml 104 | coverage.xml 105 | *,cover 106 | .hypothesis/ 107 | 108 | # Translations 109 | *.mo 110 | *.pot 111 | 112 | # Django stuff: 113 | *.log 114 | local_settings.py 115 | 116 | # Flask stuff: 117 | instance/ 118 | .webassets-cache 119 | 120 | # Scrapy stuff: 121 | .scrapy 122 | 123 | # Sphinx documentation 124 | docs/_build/ 125 | 126 | # PyBuilder 127 | target/ 128 | 129 | # Jupyter Notebook 130 | .ipynb_checkpoints 131 | 132 | # pyenv 133 | .python-version 134 | 135 | # celery beat schedule file 136 | celerybeat-schedule 137 | 138 | # SageMath parsed files 139 | *.sage.py 140 | 141 | # dotenv 142 | .env 143 | 144 | # virtualenv 145 | .venv 146 | venv/ 147 | ENV/ 148 | 149 | # Spyder project settings 150 | .spyderproject 151 | 152 | # Rope project settings 153 | .ropeproject 154 | 155 | /.idea 156 | .idea 157 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | [![Build Status](https://avatars1.githubusercontent.com/u/35299314?s=200&v=4)](https://github.com/balemessenger) 3 | 4 | ## [1.7.14] - 2019-03-02 5 | ### Added 6 | - exact_keywords argument to text_filter and template_response_filter 7 | - termination signal handling 8 | - sengin to channel by nickName 9 | ### fixed 10 | - code examples 11 | - base_url added to updater arguments 12 | - set default group shield to off 13 | 14 | ## [1.6.12] - 2019-01-08 15 | ### Added 16 | - get_quoted_message and get_quoted_sender_peer_id to 17 | FatSeqUpdate for getting replied and forwarded messages 18 | - default photo and message type limitation for purchase message 19 | - get_receipt function to BankMessage for getting receipt info as a named tuple 20 | - get_receipt and get_quoted_message examples 21 | ### fixed 22 | - filters problem 23 | - handle monitoring hash function problem 24 | - some code examples 25 | 26 | ## [1.5.11] - 2019-01-03 27 | ### Added 28 | - added validator parameter to filters as a callable function to validate the inputs 29 | - added text field among with text_message filed to template response message for unifying 30 | with other classes text field 31 | ### fixed 32 | - state holder problem at stop 33 | 34 | ## [1.4.10] - 2018-12-23 35 | ### Added 36 | - Quoted Message Handler 37 | - default action and value for template_message_button 38 | - group_shield to config for preventing bot to handle updates from group_peer 39 | - saving bot state_machine to redis db through state_holder and redis configs in config 40 | - template_message, location_message and contact_message load_from_json 41 | 42 | ### fixed 43 | - bot.send_document 44 | 45 | 46 | ## [1.3.9] - 2018-12-05 47 | ### Added 48 | - get_response method in response class 49 | - IPG payment message 50 | - healthy socket connection 51 | 52 | ## [1.2.8] - 2018-09-30 53 | ### Added 54 | - Send photo message easier than the past. 55 | - Send Document message easier than the past. 56 | 57 | 58 | ### fixed 59 | - network connection 60 | 61 | 62 | -------------------------------------------------------------------------------- /Config.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | 4 | 5 | class Config: 6 | base_url = os.environ.get('BASE_URL', "wss://api.bale.ai/v1/bots/") 7 | request_timeout = int(os.environ.get('REQUEST_TIMEOUT', 15)) 8 | # 0:print to output 1:use graylog 2:both 0 and 1 9 | use_graylog = os.environ.get('SDK_USE_GRAYLOG', "2") 10 | graylog_host = os.environ.get('SDK_GRAYLOG_HOST', "127.0.0.1") 11 | graylog_port = int(os.environ.get('SDK_GRAYLOG_PORT', "12201")) 12 | log_level = int(os.environ.get('SDK_LOG_LEVEL', logging.DEBUG)) 13 | log_facility_name = os.environ.get('SDK_LOG_FACILITY_NAME', "python_bale_bot") 14 | source = os.environ.get('LOG_SOURCE', "bot_source") 15 | heartbeat = int(os.environ.get("HEARTBEAT", 30)) 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### DEPRECATED 2 | please visit [developers guid](https://dev.bale.ai) 3 | # Bale bot python 4 | [![Build Status](https://avatars1.githubusercontent.com/u/35299314?s=200&v=4)](https://github.com/balemessenger) 5 | 6 | Python SDK and samples for [Bale bot messenger](https://developers.bale.ai). 7 | 8 | 9 | ### Register for an Access Token 10 | 11 | You'll need to create your bot by [@Bot_Father](https://web.bale.ai/). Bot_Father gives you a Token to start. 12 | 13 | ### Installation 14 | 15 | ```bash 16 | pip install -r requirements.txt 17 | ``` 18 | 19 | ### Usage 20 | 21 | ```python 22 | import asyncio 23 | 24 | from balebot.filters import * 25 | from balebot.handlers import MessageHandler, CommandHandler 26 | from balebot.models.messages import * 27 | from balebot.updater import Updater 28 | 29 | updater = Updater(token="Bot_token", 30 | loop=asyncio.get_event_loop()) 31 | bot = updater.bot 32 | dispatcher = updater.dispatcher 33 | 34 | ``` 35 | 36 | __Note__: You need to set Config.py if you want to use the logger class 37 | 38 | 39 | ##### Simple communication with client 40 | 41 | > Allows you to hear from client and answer. 42 | 43 | 44 | ```python 45 | @dispatcher.message_handler(filters=TextFilter(keywords=["hello"])) # filter text the client enter to bot 46 | def hear(bot, update): 47 | message = TextMessage('Hello') 48 | user_peer = update.get_effective_user() 49 | bot.send_message(message, user_peer, success_callback=success, failure_callback=failure) 50 | ``` 51 | 52 | 53 | ##### Sending a simple voice message: 54 | __Note__:You should upload the voice file first. 55 | 56 | > Allows you to send a voice message. (You can also send a document in the same way). 57 | 58 | 59 | ```python 60 | def send_voice(bot, update): 61 | user_peer = update.get_effective_user() 62 | v_message = VoiceMessage(file_id=file_id, access_hash=access_hash, name="Hello", file_size='259969', 63 | mime_type="audio/mpeg", 64 | duration=20, file_storage_version=1) 65 | bot.send_message(v_message, user_peer, success_callback=success, failure_callback=failure) 66 | ``` 67 | 68 | ##### Sending a generic template message: 69 | 70 | __Note__:Generic Template Messages 71 | > Allows you to add cool text buttons to a general message. 72 | 73 | ```python 74 | def ask_question(bot, update): 75 | general_message = TextMessage("a message") 76 | btn_list = [TemplateMessageButton(text="yes", value="yes", action=0), 77 | TemplateMessageButton(text="no", value="no", action=0)] 78 | template_message = TemplateMessage(general_message=general_message, btn_list=btn_list) 79 | bot.send_message(template_message, user_peer, success_callback=success, failure_callback=failure) 80 | ``` 81 | 82 | 83 | ##### Sending a generic purchase message: 84 | 85 | > Allows you send a purchase message. Clients can pay the money requested by the message by pressing "pay" button. 86 | 87 | ```python 88 | 89 | @dispatcher.message_handler(PhotoFilter()) 90 | def purchase_message(bot, update): 91 | message = update.get_effective_message() 92 | user_peer = update.get_effective_user() 93 | first_purchase_message = PurchaseMessage(msg=message, account_number=6037991067471130, amount=10, 94 | money_request_type=MoneyRequestType.normal) 95 | bot.send_message(first_purchase_message, user_peer, success_callback=success, failure_callback=failure) 96 | dispatcher.finish_conversation(update) 97 | ``` 98 | 99 | visit [bale-developers](https://developers.bale.ai) for more information 100 | 101 | -------------------------------------------------------------------------------- /balebot/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/__init__.py -------------------------------------------------------------------------------- /balebot/__version__.py: -------------------------------------------------------------------------------- 1 | 2 | __title__ = 'balebot' 3 | __description__ = 'Python framework for Bale messenger Bot API' 4 | __url__ = 'https://github.com/balemessenger/bale-bot-python' 5 | __version__ = '1.8.15' 6 | __author__ = 'bale' 7 | __author_email__ = 'balebot@elenoon.ir' 8 | __license__ = 'Apache 2.0' 9 | -------------------------------------------------------------------------------- /balebot/bale_future.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | 4 | class BaleFuture: 5 | def __init__(self, request_id, response_body_module, response_body_class, 6 | success_callback=None, failure_callback=None, **kwargs): 7 | 8 | self.request_id = str(request_id) 9 | self.response_body_module = response_body_module 10 | self.response_body_class = response_body_class 11 | self.success_callback = success_callback if isinstance(success_callback, collections.Callable) else None 12 | self.failure_callback = failure_callback if isinstance(failure_callback, collections.Callable) else None 13 | self.user_data = kwargs if kwargs else {} 14 | 15 | def set_user_data(self, **kwargs): 16 | if kwargs: 17 | self.user_data.update(kwargs) 18 | 19 | def resolve(self, response): 20 | if self.success_callback: 21 | self.success_callback(response, self.user_data) 22 | 23 | def reject(self, response): 24 | if self.failure_callback: 25 | self.failure_callback(response, self.user_data) 26 | -------------------------------------------------------------------------------- /balebot/config.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | 4 | 5 | class Config: 6 | receive_timeout = int(os.environ.get("SESSION_TIMEOUT", 60)) 7 | base_url = os.environ.get('BASE_URL', "wss://api.bale.ai/v1/bots/") 8 | request_timeout = int(os.environ.get('REQUEST_TIMEOUT', 15)) 9 | # 0:print to output 1:use graylog 2:both 0 and 1 10 | use_graylog = os.environ.get('SDK_USE_GRAYLOG', "0") 11 | source = os.environ.get('LOG_SOURCE', "bot_source") 12 | graylog_host = os.environ.get('SDK_GRAYLOG_HOST', "172.30.41.67") 13 | graylog_port = int(os.environ.get('SDK_GRAYLOG_PORT', 12201)) 14 | log_level = int(os.environ.get('SDK_LOG_LEVEL', logging.DEBUG)) 15 | log_facility_name = os.environ.get('SDK_LOG_FACILITY_NAME', "python_bale_bot") 16 | monitoring_hash = os.environ.get('MONITORING_HASH', "kjs3cns6uuw7b8cgx14d2asf41f2a2fd45sp-") 17 | real_time_fetch_updates = os.environ.get('REAL_TIME_FETCH_UPDATES', True) 18 | continue_last_processed_seq = os.environ.get('CONTINUE_LAST_PROCESSED_SEQ', False) 19 | timeInterval = int(os.environ.get('TIME_INTERVAL', 1)) # unit for time interval is second) 20 | updates_number = int(os.environ.get('UPDATES_NUMBER', 3)) 21 | heartbeat = int(os.environ.get("HEARTBEAT", 30)) 22 | state_holder = int(os.getenv('STATE_HOLDER', 0)) 23 | redis_host = os.getenv('REDIS_HOST', "localhost") 24 | redis_port = int(os.getenv('REDIS_PORT', 6379)) 25 | redis_db = os.getenv('REDIS_DB', 0) 26 | group_shield = int(os.getenv('GROUP_SHIELD', 0)) 27 | -------------------------------------------------------------------------------- /balebot/connection/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/connection/__init__.py -------------------------------------------------------------------------------- /balebot/filters/__init__.py: -------------------------------------------------------------------------------- 1 | from balebot.filters.default import DefaultFilter 2 | from balebot.filters.document_filter import DocumentFilter 3 | from balebot.filters.filter import Filter 4 | from balebot.filters.json_filter import JsonFilter 5 | from balebot.filters.photo_filter import PhotoFilter 6 | from balebot.filters.sticker_filter import StickerFilter 7 | from balebot.filters.text_filter import TextFilter 8 | from balebot.filters.unsupported_filter import UnsupportedFilter 9 | from balebot.filters.video_filter import VideoFilter 10 | from balebot.filters.voice_filter import VoiceFilter 11 | from balebot.filters.template_response_filter import TemplateResponseFilter 12 | from balebot.filters.contact_filter import ContactFilter 13 | from balebot.filters.location_filter import LocationFilter 14 | from balebot.filters.bank_message_filter import BankMessageFilter 15 | from balebot.filters.template_message_filter import TemplateMessageFilter 16 | 17 | -------------------------------------------------------------------------------- /balebot/filters/bank_message_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.banking.bank_message import BankMessage 2 | from balebot.filters.filter import Filter 3 | 4 | 5 | class BankMessageFilter(Filter): 6 | def match(self, message): 7 | if isinstance(message, BankMessage): 8 | return self.validator(message) if self.validator else True 9 | else: 10 | return False 11 | -------------------------------------------------------------------------------- /balebot/filters/contact_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.contact_message import ContactMessage 2 | from balebot.models.messages.json_message import JsonMessage 3 | from balebot.filters.filter import Filter 4 | 5 | 6 | class ContactFilter(Filter): 7 | def match(self, message): 8 | return isinstance(message, ContactMessage) 9 | -------------------------------------------------------------------------------- /balebot/filters/default.py: -------------------------------------------------------------------------------- 1 | from balebot.filters.filter import Filter 2 | 3 | 4 | class DefaultFilter(Filter): 5 | def match(self, message): 6 | return True 7 | -------------------------------------------------------------------------------- /balebot/filters/document_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.filters.filter import Filter 2 | from balebot.models.messages.document_message import DocumentMessage 3 | 4 | 5 | class DocumentFilter(Filter): 6 | def match(self, message): 7 | return isinstance(message, DocumentMessage) and DocumentMessage.is_raw_document_message( 8 | message.get_json_object()) 9 | -------------------------------------------------------------------------------- /balebot/filters/filter.py: -------------------------------------------------------------------------------- 1 | class Filter: 2 | def __init__(self, validator=None): 3 | self.validator = validator if callable(validator) else None 4 | 5 | def match(self, message): 6 | raise NotImplementedError 7 | 8 | def validate(self, obj): 9 | return self.validator(obj) if self.validator else False 10 | -------------------------------------------------------------------------------- /balebot/filters/json_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.json_message import JsonMessage 2 | from balebot.filters.filter import Filter 3 | 4 | 5 | class JsonFilter(Filter): 6 | def match(self, message): 7 | return isinstance(message, JsonMessage) 8 | -------------------------------------------------------------------------------- /balebot/filters/location_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.filters.filter import Filter 2 | from balebot.models.messages.location_message import LocationMessage 3 | 4 | 5 | class LocationFilter(Filter): 6 | def match(self, message): 7 | if isinstance(message, LocationMessage): 8 | return self.validator(message) if self.validator else True 9 | else: 10 | return False 11 | -------------------------------------------------------------------------------- /balebot/filters/photo_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.photo_message import PhotoMessage 2 | from balebot.filters.filter import Filter 3 | 4 | 5 | class PhotoFilter(Filter): 6 | def match(self, message): 7 | if isinstance(message, PhotoMessage): 8 | return self.validator(message) if self.validator else True 9 | else: 10 | return False 11 | -------------------------------------------------------------------------------- /balebot/filters/sticker_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.sticker_message import StickerMessage 2 | from balebot.filters.filter import Filter 3 | 4 | 5 | class StickerFilter(Filter): 6 | def match(self, message): 7 | return isinstance(message, StickerMessage) 8 | -------------------------------------------------------------------------------- /balebot/filters/template_message_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.template.template_message import TemplateMessage 2 | from balebot.filters.filter import Filter 3 | 4 | 5 | class TemplateMessageFilter(Filter): 6 | def match(self, message): 7 | return isinstance(message, TemplateMessage) 8 | -------------------------------------------------------------------------------- /balebot/filters/template_response_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.template_response_message import TemplateResponseMessage 2 | import re 3 | from balebot.filters.filter import Filter 4 | 5 | 6 | class TemplateResponseFilter(Filter): 7 | def __init__(self, keywords=None, exact_keywords=None, pattern=None, validator=None, include_commands=True): 8 | super(TemplateResponseFilter, self).__init__(validator) 9 | self.keywords = [] 10 | self.exact_keywords = [] 11 | if isinstance(keywords, list): 12 | self.keywords += keywords 13 | elif isinstance(keywords, str): 14 | self.keywords.append(keywords) 15 | if isinstance(exact_keywords, list): 16 | self.exact_keywords += exact_keywords 17 | elif isinstance(exact_keywords, str): 18 | self.exact_keywords.append(exact_keywords) 19 | 20 | self.pattern = pattern 21 | self.validator = validator if callable(validator) else None 22 | self.include_commands = include_commands 23 | 24 | def match(self, message): 25 | if isinstance(message, TemplateResponseMessage): 26 | text = message.text 27 | if not self.include_commands and text.startswith("/"): 28 | return False 29 | if not self.pattern and not self.keywords and not self.validator and not self.exact_keywords: 30 | return True 31 | elif self.find_keywords(text): 32 | return True 33 | elif self.find_exact_keywords(text): 34 | return True 35 | elif self.find_pattern(text): 36 | return True 37 | elif self.validate(text): 38 | return True 39 | else: 40 | return False 41 | 42 | def find_keywords(self, text): 43 | for keyword in self.keywords: 44 | if keyword: 45 | if text.find(keyword) != -1: 46 | return True 47 | return False 48 | 49 | def find_exact_keywords(self, text): 50 | for exact_keyword in self.exact_keywords: 51 | if exact_keyword == text: 52 | return True 53 | return False 54 | 55 | def find_pattern(self, text): 56 | if self.pattern: 57 | return re.search(self.pattern, text) 58 | else: 59 | return False 60 | -------------------------------------------------------------------------------- /balebot/filters/text_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.text_message import TextMessage 2 | import re 3 | from balebot.filters.filter import Filter 4 | 5 | 6 | class TextFilter(Filter): 7 | def __init__(self, keywords=None, exact_keywords=None, pattern=None, validator=None, include_commands=True): 8 | super(TextFilter, self).__init__(validator) 9 | self.keywords = [] 10 | self.exact_keywords = [] 11 | if isinstance(keywords, list): 12 | self.keywords += keywords 13 | elif isinstance(keywords, str): 14 | self.keywords.append(keywords) 15 | if isinstance(exact_keywords, list): 16 | self.exact_keywords += exact_keywords 17 | elif isinstance(exact_keywords, str): 18 | self.exact_keywords.append(exact_keywords) 19 | 20 | self.pattern = pattern 21 | self.validator = validator if callable(validator) else None 22 | self.include_commands = include_commands 23 | 24 | def match(self, message): 25 | if isinstance(message, TextMessage): 26 | text = message.text 27 | if not self.include_commands and text.startswith("/"): 28 | return False 29 | if not self.pattern and not self.keywords and not self.validator and not self.exact_keywords: 30 | return True 31 | elif self.find_keywords(text): 32 | return True 33 | elif self.find_exact_keywords(text): 34 | return True 35 | elif self.find_pattern(text): 36 | return True 37 | elif self.validate(text): 38 | return True 39 | else: 40 | return False 41 | 42 | def find_keywords(self, text): 43 | for exact_keyword in self.keywords: 44 | if exact_keyword == text: 45 | return True 46 | return False 47 | 48 | def find_exact_keywords(self, text): 49 | for keyword in self.exact_keywords: 50 | if keyword == text: 51 | return True 52 | return False 53 | 54 | def find_pattern(self, text): 55 | if self.pattern: 56 | return re.search(self.pattern, text) 57 | return False 58 | -------------------------------------------------------------------------------- /balebot/filters/unsupported_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.unsupported_message import UnsupportedMessage 2 | from balebot.filters.filter import Filter 3 | 4 | 5 | class UnsupportedFilter(Filter): 6 | def match(self, message): 7 | return isinstance(message, UnsupportedMessage) 8 | -------------------------------------------------------------------------------- /balebot/filters/video_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.video_message import VideoMessage 2 | from balebot.filters.filter import Filter 3 | 4 | 5 | class VideoFilter(Filter): 6 | def match(self, message): 7 | if isinstance(message, VideoMessage): 8 | return self.validator(message) if self.validator else True 9 | else: 10 | return False 11 | -------------------------------------------------------------------------------- /balebot/filters/voice_filter.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.voice_message import VoiceMessage 2 | from balebot.filters.filter import Filter 3 | 4 | 5 | class VoiceFilter(Filter): 6 | def match(self, message): 7 | if isinstance(message, VoiceMessage): 8 | return self.validator(message) if self.validator else True 9 | else: 10 | return False 11 | -------------------------------------------------------------------------------- /balebot/handlers/__init__.py: -------------------------------------------------------------------------------- 1 | from balebot.handlers.handler import Handler 2 | from balebot.handlers.command_handler import CommandHandler 3 | from balebot.handlers.message_handler import MessageHandler 4 | from balebot.handlers.quoted_message_handler import QuotedMessageHandler 5 | -------------------------------------------------------------------------------- /balebot/handlers/command_handler.py: -------------------------------------------------------------------------------- 1 | from balebot.handlers.handler import Handler 2 | from balebot.models.base_models.fat_seq_update import FatSeqUpdate 3 | from balebot.models.messages.template_response_message import TemplateResponseMessage 4 | from balebot.models.messages.text_message import TextMessage 5 | 6 | 7 | class CommandHandler(Handler): 8 | def __init__(self, commands, callback, include_template_response=False): 9 | super(CommandHandler, self).__init__(callback=callback) 10 | if isinstance(commands, str): 11 | commands = [commands.lower()] 12 | elif isinstance(commands, list): 13 | commands = [command.lower() for command in commands] 14 | self.commands = [(command[1:] if command.startswith("/") else command) for command in commands] 15 | self.include_template_response = include_template_response 16 | 17 | def check_update(self, update): 18 | if isinstance(update, FatSeqUpdate) and update.is_message_update(): 19 | message = update.get_effective_message() 20 | if isinstance(message, TextMessage): 21 | message_text = message.text.lower() 22 | elif self.include_template_response and isinstance(message, TemplateResponseMessage): 23 | message_text = message.text_message.lower() 24 | else: 25 | return False 26 | 27 | if not message_text.startswith("/"): 28 | return False 29 | 30 | message_command = message_text[1:].split(" ")[0] 31 | 32 | return any(message_command == command for command in self.commands) 33 | return False 34 | 35 | def handle_update(self, dispatcher, update): 36 | return self.callback(bot=dispatcher.bot, update=update) 37 | 38 | def is_default_handler(self): 39 | return False 40 | -------------------------------------------------------------------------------- /balebot/handlers/handler.py: -------------------------------------------------------------------------------- 1 | class Handler: 2 | def __init__(self, callback): 3 | self.callback = callback 4 | 5 | def check_update(self, update): 6 | raise NotImplementedError 7 | 8 | def handle_update(self, dispatcher, update): 9 | raise NotImplementedError 10 | 11 | def is_default_handler(self): 12 | raise NotImplementedError 13 | -------------------------------------------------------------------------------- /balebot/handlers/message_handler.py: -------------------------------------------------------------------------------- 1 | from balebot.filters import DefaultFilter 2 | from balebot.filters.filter import Filter 3 | from balebot.handlers.handler import Handler 4 | from balebot.models.base_models.fat_seq_update import FatSeqUpdate 5 | 6 | 7 | class MessageHandler(Handler): 8 | def __init__(self, filters, callback): 9 | super(MessageHandler, self).__init__(callback=callback) 10 | 11 | if not filters: 12 | filters = DefaultFilter() 13 | 14 | if isinstance(filters, list) and all( 15 | isinstance(message_filter, Filter) for message_filter in filters): 16 | self.filters = filters 17 | elif isinstance(filters, Filter): 18 | self.filters = [filters] 19 | else: 20 | raise ValueError("filters don't have acceptable format.") 21 | 22 | def check_update(self, update): 23 | if isinstance(update, FatSeqUpdate) and update.is_message_update(): 24 | message = update.get_effective_message() 25 | 26 | return any(message_filter.match(message) for message_filter in self.filters) 27 | 28 | def handle_update(self, dispatcher, update): 29 | return self.callback(bot=dispatcher.bot, update=update) 30 | 31 | def is_default_handler(self): 32 | for message_filter in self.filters: 33 | if isinstance(message_filter, DefaultFilter): 34 | return True 35 | -------------------------------------------------------------------------------- /balebot/handlers/quoted_message_handler.py: -------------------------------------------------------------------------------- 1 | from balebot.filters import DefaultFilter 2 | from balebot.filters.filter import Filter 3 | from balebot.handlers.handler import Handler 4 | from balebot.models.base_models.fat_seq_update import FatSeqUpdate 5 | 6 | 7 | class QuotedMessageHandler(Handler): 8 | def __init__(self, filters, callback): 9 | super(QuotedMessageHandler, self).__init__(callback=callback) 10 | 11 | if not filters: 12 | filters = DefaultFilter() 13 | 14 | if isinstance(filters, list) and all( 15 | isinstance(message_filter, Filter) for message_filter in filters): 16 | self.filters = filters 17 | elif isinstance(filters, Filter): 18 | self.filters = [filters] 19 | else: 20 | raise ValueError("filters don't have acceptable format.") 21 | 22 | def check_update(self, update): 23 | if isinstance(update, FatSeqUpdate) and update.is_message_update() and update.body.quoted_message: 24 | message = update.body.quoted_message.message 25 | 26 | return any(message_filter.match(message) for message_filter in self.filters) 27 | 28 | def handle_update(self, dispatcher, update): 29 | return self.callback(bot=dispatcher.bot, update=update) 30 | 31 | def is_default_handler(self): 32 | for message_filter in self.filters: 33 | if isinstance(message_filter, DefaultFilter): 34 | return True 35 | -------------------------------------------------------------------------------- /balebot/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/__init__.py -------------------------------------------------------------------------------- /balebot/models/base_models/__init__.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models.avatar import Avatar 2 | from balebot.models.base_models.bot_api_quoted_message import BotApiQuotedMessage 3 | from balebot.models.base_models.bot_command import BotCommand 4 | from balebot.models.base_models.bot_quoted_message import BotQuotedMessage 5 | from balebot.models.base_models.contact_record import ContactRecord 6 | from balebot.models.base_models.fat_seq_update import FatSeqUpdate 7 | from balebot.models.base_models.file_location import FileLocation 8 | from balebot.models.base_models.group import Group 9 | from balebot.models.base_models.group_member import GroupMember 10 | from balebot.models.base_models.group_peer import GroupPeer 11 | from balebot.models.base_models.image_location import ImageLocation 12 | from balebot.models.base_models.jsonable import Jsonable 13 | from balebot.models.base_models.member import Member 14 | from balebot.models.base_models.pack_info import PackInfo 15 | from balebot.models.base_models.peer import Peer 16 | from balebot.models.base_models.request import Request 17 | from balebot.models.base_models.request_body import RequestBody 18 | from balebot.models.base_models.response import Response 19 | from balebot.models.base_models.response_body import ResponseBody 20 | from balebot.models.base_models.user import User 21 | from balebot.models.base_models.user_peer import UserPeer 22 | from balebot.models.base_models.raw_json import RawJson 23 | -------------------------------------------------------------------------------- /balebot/models/base_models/avatar.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | from balebot.models.constants.errors import Error 3 | 4 | from balebot.models.base_models.image_location import ImageLocation 5 | 6 | from balebot.models.base_models.jsonable import Jsonable 7 | 8 | 9 | class Avatar(Jsonable): 10 | def __init__(self, small_image=None, large_image=None, full_image=None): 11 | 12 | if small_image: 13 | if isinstance(small_image, ImageLocation): 14 | self.small_image = small_image 15 | else: 16 | raise ValueError(Error.unacceptable_object_type) 17 | else: 18 | self.small_image = None 19 | 20 | if large_image: 21 | if isinstance(large_image, ImageLocation): 22 | self.large_image = large_image 23 | else: 24 | raise ValueError(Error.unacceptable_object_type) 25 | else: 26 | self.large_image = None 27 | 28 | if full_image: 29 | if isinstance(full_image, ImageLocation): 30 | self.full_image = full_image 31 | else: 32 | raise ValueError(Error.unacceptable_object_type) 33 | else: 34 | self.full_image = None 35 | 36 | def get_json_object(self): 37 | 38 | data = { 39 | "smallImage": self.small_image.get_json_object(), 40 | "largeImage": self.large_image.get_json_object(), 41 | "fullImage": self.full_image.get_json_object(), 42 | } 43 | 44 | return data 45 | 46 | def get_json_str(self): 47 | return json_handler.dumps(self.get_json_object()) 48 | 49 | @classmethod 50 | def load_from_json(cls, json): 51 | if isinstance(json, dict): 52 | json_dict = json 53 | elif isinstance(json, str): 54 | json_dict = json_handler.loads(json) 55 | else: 56 | raise ValueError(Error.unacceptable_json) 57 | 58 | small_image = ImageLocation.load_from_json(json_dict.get("smallImage", None)) \ 59 | if json_dict.get("smallImage", None) else None 60 | large_image = ImageLocation.load_from_json(json_dict.get("largeImage", None)) \ 61 | if json_dict.get("largeImage", None) else None 62 | full_image = ImageLocation.load_from_json(json_dict.get("fullImage", None)) \ 63 | if json_dict.get("fullImage", None) else None 64 | 65 | return cls(small_image=small_image, large_image=large_image, full_image=full_image) 66 | -------------------------------------------------------------------------------- /balebot/models/base_models/banking/__init__.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models.banking.bank_account import BankAccount 2 | -------------------------------------------------------------------------------- /balebot/models/base_models/banking/bank_account.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.constants.errors import Error 4 | 5 | 6 | class BankAccount: 7 | def __init__(self, account_number, branch_code, open_date, rate, available_balance, 8 | last_money_transfer_date, first_name, last_name): 9 | 10 | self._account_number = str(account_number) 11 | self._branch_code = int(branch_code) 12 | self._open_date = str(open_date) 13 | self._rate = int(rate) 14 | self._available_balance = str(available_balance) 15 | self._last_money_transfer_date = str(last_money_transfer_date) 16 | self._first_name = str(first_name) 17 | self._last_name = str(last_name) 18 | 19 | def get_json_object(self): 20 | data = { 21 | "accountNumber": self._account_number, 22 | "branchCode": self._branch_code, 23 | "openDate": self._open_date, 24 | "rate": self._rate, 25 | "availableBalance": self._available_balance, 26 | "lastMoneyTransferDate": self._last_money_transfer_date, 27 | "firstName": self._first_name, 28 | "lastName": self._last_name, 29 | 30 | } 31 | return data 32 | 33 | def get_json_str(self): 34 | return json_handler.dumps(self.get_json_object()) 35 | 36 | @classmethod 37 | def load_from_json(cls, json): 38 | if isinstance(json, dict): 39 | json_dict = json 40 | elif isinstance(json, str): 41 | json_dict = json_handler.loads(json) 42 | else: 43 | raise ValueError(Error.unacceptable_json) 44 | 45 | account_number = json_dict.get('accountNumber', None) 46 | branch_code = json_dict.get('branchCode', None) 47 | open_date = json_dict.get('openDate', None) 48 | rate = json_dict.get('rate', None) 49 | available_balance = json_dict.get('availableBalance', None) 50 | last_money_transfer_date = json_dict.get('lastMoneyTransferDate', None) 51 | first_name = json_dict.get('firstName', None) 52 | last_name = json_dict.get('lastName', None) 53 | 54 | if (not account_number) or (branch_code is None) or (not open_date) or (rate is None) \ 55 | or (available_balance is None) or (not last_money_transfer_date) \ 56 | or (not first_name) or (not last_name): 57 | raise ValueError(Error.none_or_invalid_attribute) 58 | 59 | return cls(account_number=account_number, branch_code=branch_code, open_date=open_date, 60 | rate=rate, available_balance=available_balance, 61 | last_money_transfer_date=last_money_transfer_date, 62 | first_name=first_name, last_name=last_name) 63 | -------------------------------------------------------------------------------- /balebot/models/base_models/banking/bank_ext.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models.jsonable import Jsonable 2 | 3 | 4 | class BankExt(Jsonable): 5 | pass 6 | -------------------------------------------------------------------------------- /balebot/models/base_models/banking/deprecated_receipt.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.banking.bank_ext import BankExt 4 | from balebot.models.base_models.value_types.map_value import MapValue 5 | from balebot.models.constants.bank_ext_types import BankExtTypes 6 | from balebot.models.constants.errors import Error 7 | from balebot.models.factories import message_factory 8 | from balebot.models.messages.base_message import BaseMessage 9 | 10 | 11 | class DeprecatedReceipt(BankExt): 12 | def __init__(self, receipt_type, transfer_info, original_message=None): 13 | self._receipt_type = receipt_type 14 | 15 | if isinstance(transfer_info, MapValue): 16 | self._transfer_info = transfer_info 17 | else: 18 | raise ValueError(Error.unacceptable_object_type) 19 | 20 | if original_message: 21 | if isinstance(original_message, BaseMessage): 22 | self._original_message = original_message 23 | else: 24 | raise ValueError(Error.unacceptable_object_type) 25 | else: 26 | self._original_message = None 27 | 28 | def get_json_object(self): 29 | data = { 30 | "$type": BankExtTypes.deprecated_receipt, 31 | "receiptType": { 32 | "$type": self._receipt_type, 33 | }, 34 | "transferInfo": self._transfer_info.get_json_object(), 35 | "originalMessage": self._original_message.get_json_object() if self._original_message else None, 36 | 37 | } 38 | return data 39 | 40 | def get_json_str(self): 41 | return json_handler.dumps(self.get_json_object()) 42 | 43 | @classmethod 44 | def load_from_json(cls, json): 45 | if isinstance(json, dict): 46 | json_dict = json 47 | elif isinstance(json, str): 48 | json_dict = json_handler.loads(json) 49 | else: 50 | raise ValueError(Error.unacceptable_json) 51 | 52 | receipt_type = json_dict.get('receiptType', None)["$type"] 53 | transfer_info = MapValue.load_from_json(json_dict.get('transferInfo', None)) 54 | original_message = message_factory.MessageFactory.create_message( 55 | json_dict.get('originalMessage', None)) if json_dict.get( 56 | 'originalMessage', None) else None 57 | 58 | if (not receipt_type) or (transfer_info is None): 59 | raise ValueError(Error.none_or_invalid_attribute) 60 | 61 | return cls(receipt_type=receipt_type, transfer_info=transfer_info, original_message=original_message) 62 | -------------------------------------------------------------------------------- /balebot/models/base_models/banking/deprecated_receipt_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.banking.bank_ext import BankExt 4 | from balebot.models.base_models.value_types.map_value import MapValue 5 | from balebot.models.constants.bank_ext_types import BankExtTypes 6 | from balebot.models.constants.errors import Error 7 | from balebot.models.factories import message_factory 8 | from balebot.models.messages.base_message import BaseMessage 9 | 10 | 11 | class DeprecatedReceiptMessage(BankExt): 12 | def __init__(self, partial_receipt_type, partial_transfer_info, partial_original_message=None, 13 | partial_original_message_rid=None): 14 | 15 | self._partial_receipt_type = str(partial_receipt_type) 16 | 17 | if isinstance(partial_transfer_info, MapValue): 18 | self._partial_transfer_info = partial_transfer_info 19 | else: 20 | raise ValueError(Error.unacceptable_object_type) 21 | 22 | if partial_original_message: 23 | if isinstance(partial_original_message, BaseMessage): 24 | self._partial_original_message = partial_original_message 25 | else: 26 | raise ValueError(Error.unacceptable_object_type) 27 | else: 28 | self._partial_original_message = None 29 | 30 | self._partial_original_message_rid = str(partial_original_message_rid) if partial_original_message_rid else None 31 | 32 | def get_json_object(self): 33 | data = { 34 | "$type": BankExtTypes.deprecated_receipt_message, 35 | "partialReceiptType": { 36 | "$type": self._partial_receipt_type, 37 | }, 38 | "partialTransferInfo": self._partial_transfer_info.get_json_object(), 39 | "partialOriginalMessage": self._partial_original_message.get_json_object() if self._partial_original_message 40 | else None, 41 | "partialOrginalMessageRID": self._partial_original_message_rid if self._partial_original_message else None, 42 | 43 | } 44 | return data 45 | 46 | def get_json_str(self): 47 | return json_handler.dumps(self.get_json_object()) 48 | 49 | @classmethod 50 | def load_from_json(cls, json): 51 | if isinstance(json, dict): 52 | json_dict = json 53 | elif isinstance(json, str): 54 | json_dict = json_handler.loads(json) 55 | else: 56 | raise ValueError(Error.unacceptable_json) 57 | 58 | partial_receipt_type = json_dict.get('partial_receipt_type', None)["$type"] 59 | partial_transfer_info = MapValue.load_from_json(json_dict.get('partial_transfer_info', None)) 60 | partial_original_message = message_factory.MessageFactory.create_message( 61 | json_dict.get('partial_original_message', None)) if json_dict.get( 62 | 'partial_original_message', None) else None 63 | partial_original_message_rid = json_dict.get('partial_original_message_rid', None) 64 | 65 | if (not partial_receipt_type) or (partial_transfer_info is None): 66 | raise ValueError(Error.none_or_invalid_attribute) 67 | 68 | return cls(partial_receipt_type=partial_receipt_type, 69 | partial_transfer_info=partial_transfer_info, 70 | partial_original_message=partial_original_message, 71 | partial_original_message_rid=partial_original_message_rid) 72 | -------------------------------------------------------------------------------- /balebot/models/base_models/banking/receipt_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.banking.bank_ext import BankExt 4 | from balebot.models.base_models.value_types.map_value import MapValue 5 | from balebot.models.constants.bank_ext_types import BankExtTypes 6 | from balebot.models.constants.errors import Error 7 | from collections import namedtuple 8 | 9 | from balebot.models.factories.raw_value_factory import RawValueFactory 10 | 11 | 12 | class ReceiptMessage(BankExt): 13 | def __init__(self, message, transfer_info): 14 | 15 | if isinstance(message, MapValue): 16 | self.message = message 17 | else: 18 | raise ValueError(Error.unacceptable_object_type) 19 | 20 | if isinstance(transfer_info, MapValue): 21 | self.transfer_info = transfer_info 22 | else: 23 | raise ValueError(Error.unacceptable_object_type) 24 | 25 | def get_json_object(self): 26 | data = { 27 | "$type": BankExtTypes.deprecated_receipt, 28 | "message": self.message.get_json_object(), 29 | "transferInfo": self.transfer_info.get_json_object(), 30 | } 31 | return data 32 | 33 | def get_json_str(self): 34 | return json_handler.dumps(self.get_json_object()) 35 | 36 | def generate_receipt_from_transfer_info_items(self): 37 | BankReceipt = namedtuple('BankReceipt', [item.key for item in self.transfer_info.items]) 38 | params = [RawValueFactory.get_value(self.transfer_info.items[i].value) 39 | for i in range(self.transfer_info.items.__len__())] 40 | bank_receipt = BankReceipt(*params) 41 | return bank_receipt 42 | 43 | @classmethod 44 | def load_from_json(cls, json): 45 | if isinstance(json, dict): 46 | json_dict = json 47 | elif isinstance(json, str): 48 | json_dict = json_handler.loads(json) 49 | else: 50 | raise ValueError(Error.unacceptable_json) 51 | 52 | message = MapValue.load_from_json(json_dict.get('message', None)) 53 | transfer_info = MapValue.load_from_json(json_dict.get('transferInfo', None)) 54 | 55 | if (message is None) or (transfer_info is None): 56 | raise ValueError(Error.none_or_invalid_attribute) 57 | 58 | return cls(message=message, transfer_info=transfer_info) 59 | -------------------------------------------------------------------------------- /balebot/models/base_models/bot_api_quoted_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | from balebot.models.constants.errors import Error 3 | 4 | from balebot.models.factories import message_factory 5 | 6 | 7 | class BotApiQuotedMessage: 8 | def __init__(self, json): 9 | if isinstance(json, dict): 10 | json_dict = json 11 | elif isinstance(json, str): 12 | json_dict = json_handler.loads(json) 13 | else: 14 | raise ValueError(Error.unacceptable_json) 15 | 16 | self.message_id = json_dict.get("messageId", None) 17 | self.public_group_id = json_dict.get("publicGroupId", None) 18 | self.sender_id = json_dict.get("senderId", None) 19 | self.messageDate = json_dict.get("messageDate", None) 20 | self.message = message_factory.MessageFactory.create_message(json_dict.get("message")) 21 | -------------------------------------------------------------------------------- /balebot/models/base_models/bot_command.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | from balebot.models.constants.errors import Error 3 | 4 | from balebot.models.base_models.jsonable import Jsonable 5 | 6 | 7 | class BotCommand(Jsonable): 8 | def __init__(self, slash_command, description, loc_key="a"): 9 | self.slash_command = str(slash_command) 10 | self.description = str(description) 11 | self.loc_key = str(loc_key) if loc_key else None 12 | 13 | def get_json_object(self): 14 | data = { 15 | "slashCommand": self.slash_command, 16 | "description": self.description, 17 | "locKey": self.loc_key, 18 | 19 | } 20 | 21 | return data 22 | 23 | def get_json_str(self): 24 | return json_handler.dumps(self.get_json_object()) 25 | 26 | @classmethod 27 | def load_from_json(cls, json): 28 | if isinstance(json, dict): 29 | json_dict = json 30 | elif isinstance(json, str): 31 | json_dict = json_handler.loads(json) 32 | else: 33 | raise ValueError(Error.unacceptable_json) 34 | 35 | slash_command = json_dict.get('slashCommand', None) 36 | description = json_dict.get('description', None) 37 | loc_key = json_dict.get('locKey', None) 38 | 39 | if (slash_command is None) or (description is None): 40 | raise ValueError(Error.none_or_invalid_attribute) 41 | 42 | return cls(slash_command=slash_command, description=description, loc_key=loc_key) 43 | -------------------------------------------------------------------------------- /balebot/models/base_models/bot_quoted_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | from balebot.models.constants.errors import Error 3 | 4 | from balebot.models.base_models.peer import Peer 5 | from balebot.models.base_models.jsonable import Jsonable 6 | 7 | 8 | class BotQuotedMessage(Jsonable): 9 | def __init__(self, message_id=None, peer=None): 10 | 11 | self.message_id = str(message_id) if message_id else None 12 | 13 | if peer: 14 | if isinstance(peer, Peer): 15 | self.peer = peer 16 | else: 17 | raise ValueError(Error.unacceptable_object_type) 18 | else: 19 | self.peer = None 20 | 21 | def get_json_object(self): 22 | data = { 23 | "messageId": self.message_id, 24 | "peer": self.peer.get_json_object() if self.peer else None, 25 | } 26 | 27 | return data 28 | 29 | def get_json_str(self): 30 | return json_handler.dumps(self.get_json_object()) 31 | 32 | @classmethod 33 | def load_from_json(cls, json): 34 | pass 35 | -------------------------------------------------------------------------------- /balebot/models/base_models/contact.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.raw_json import RawJson 4 | from balebot.models.constants.errors import Error 5 | from balebot.models.constants.raw_json_type import RawJsonType 6 | 7 | 8 | class Contact(RawJson): 9 | def __init__(self, name, emails, phones): 10 | self.name = str(name) 11 | 12 | if isinstance(emails, list): 13 | self.emails = [str(email) for email in emails] 14 | else: 15 | raise ValueError(Error.unacceptable_object_type) 16 | 17 | if isinstance(phones, list): 18 | self.phones = ["".join(str(phone).split(" ")) for phone in phones] 19 | else: 20 | raise ValueError(Error.unacceptable_object_type) 21 | 22 | def get_json_object(self): 23 | data = { 24 | "dataType": RawJsonType.contact, 25 | "data": { 26 | RawJsonType.contact: { 27 | "name": self.name, 28 | "emails": self.emails, 29 | "phones": self.phones 30 | } 31 | } 32 | } 33 | 34 | return data 35 | 36 | def get_json_str(self): 37 | return json_handler.dumps(self.get_json_object()) 38 | 39 | @classmethod 40 | def load_from_json(cls, json): 41 | if isinstance(json, dict): 42 | json_dict = json 43 | elif isinstance(json, str): 44 | json_dict = json_handler.loads(json) 45 | else: 46 | raise ValueError(Error.unacceptable_json) 47 | 48 | data = json_dict.get('data', None) 49 | contact = data.get(RawJsonType.contact, None) 50 | name = contact.get('name', None) 51 | emails = contact.get('emails', None) 52 | phones = contact.get('phones', None) 53 | 54 | return cls(name=name, emails=emails, phones=phones) 55 | -------------------------------------------------------------------------------- /balebot/models/base_models/contact_record.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | from balebot.models.constants.errors import Error 3 | 4 | 5 | class ContactRecord: 6 | def __init__(self, json): 7 | if isinstance(json, dict): 8 | json_dict = json 9 | elif isinstance(json, str): 10 | json_dict = json_handler.loads(json) 11 | else: 12 | raise ValueError(Error.unacceptable_json) 13 | 14 | self.type = json_dict.get("$type", None) 15 | 16 | if self.type == "Email": 17 | self.email = json_dict.get("email", None) 18 | 19 | elif self.type == "Phone": 20 | self.phone = json_dict.get("phone", None) 21 | -------------------------------------------------------------------------------- /balebot/models/base_models/fat_seq_update.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | from balebot.models.constants.errors import Error 3 | 4 | from balebot.models.base_models.group import Group 5 | from balebot.models.base_models.user import User 6 | from balebot.models.factories import update_body_factory 7 | from balebot.models.server_updates.bot_read_update_body import BotReadUpdate 8 | from balebot.models.server_updates.message_update_body import MessageUpdate 9 | from balebot.models.server_updates.raw_update_body import RawUpdate 10 | 11 | from balebot.models.server_updates.bot_received_update_body import BotReceivedUpdate 12 | 13 | 14 | class FatSeqUpdate: 15 | def __init__(self, json): 16 | if isinstance(json, dict): 17 | json_dict = json 18 | elif isinstance(json, str): 19 | json_dict = json_handler.loads(json) 20 | else: 21 | raise ValueError(Error.unacceptable_json) 22 | 23 | self.json_dict = json_dict 24 | self.seq = json_dict.get("seq", None) 25 | 26 | self.body = update_body_factory.UpdateBodyFactory.create_update_body(json_dict.get("body", None)) 27 | 28 | temp_users = json_dict.get("users", None) 29 | self.users = [User.load_from_json(user[1]) for user in temp_users] 30 | 31 | temp_groups = json_dict.get("groups", None) 32 | self.groups = [Group.load_from_json(group[1]) for group in temp_groups] 33 | 34 | def is_message_update(self): 35 | return isinstance(self.body, MessageUpdate) 36 | 37 | def is_read_update(self): 38 | return isinstance(self.body, BotReadUpdate) 39 | 40 | def is_received_update(self): 41 | return isinstance(self.body, BotReceivedUpdate) 42 | 43 | def is_raw_update(self): 44 | return isinstance(self.body, RawUpdate) 45 | 46 | def get_effective_user(self): 47 | user = None 48 | if self.is_message_update(): 49 | user = self.body.peer 50 | elif self.is_received_update(): 51 | user = self.body.peer 52 | elif self.is_read_update(): 53 | user = self.body.peer 54 | return user 55 | 56 | def get_effective_message(self): 57 | message = None 58 | if self.is_message_update(): 59 | message = self.body.message 60 | return message 61 | 62 | def get_quoted_message(self): 63 | quoted_message = None 64 | if self.is_message_update(): 65 | if self.body.quoted_message: 66 | quoted_message = self.body.quoted_message.message 67 | return quoted_message 68 | 69 | def get_quoted_sender_peer_id(self): 70 | user_id = None 71 | if self.is_message_update(): 72 | if self.body.quoted_message: 73 | user_id = self.body.quoted_message.sender_id 74 | return user_id 75 | -------------------------------------------------------------------------------- /balebot/models/base_models/file_location.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | from balebot.models.constants.errors import Error 3 | 4 | from balebot.models.base_models.jsonable import Jsonable 5 | 6 | 7 | class FileLocation(Jsonable): 8 | def __init__(self, file_id, access_hash, file_storage_version=1): 9 | self.file_id = str(file_id) 10 | self.access_hash = str(access_hash) 11 | self.file_storage_version = int(file_storage_version) 12 | 13 | def get_json_object(self): 14 | data = { 15 | "fileId": self.file_id, 16 | "accessHash": self.access_hash, 17 | "fileStorageVersion": self.file_storage_version 18 | } 19 | 20 | return data 21 | 22 | def get_json_str(self): 23 | return json_handler.dumps(self.get_json_object()) 24 | 25 | @classmethod 26 | def load_from_json(cls, json): 27 | if isinstance(json, dict): 28 | json_dict = json 29 | elif isinstance(json, str): 30 | json_dict = json_handler.loads(json) 31 | else: 32 | raise ValueError(Error.unacceptable_json) 33 | 34 | file_id = json_dict.get('fileId', None) 35 | access_hash = json_dict.get('accessHash', None) 36 | file_storage_version = json_dict.get('fileStorageVersion', None) 37 | 38 | if (not file_id) or (not access_hash): 39 | raise ValueError(Error.none_or_invalid_attribute) 40 | 41 | return cls(file_id=file_id, access_hash=access_hash, file_storage_version=file_storage_version) 42 | -------------------------------------------------------------------------------- /balebot/models/base_models/group.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | from balebot.models.constants.errors import Error 3 | 4 | from balebot.models.base_models.avatar import Avatar 5 | from balebot.models.base_models.group_member import GroupMember 6 | 7 | from balebot.models.base_models.jsonable import Jsonable 8 | 9 | 10 | class Group(Jsonable): 11 | def __init__(self, group_id, access_hash, title, is_member, creator_user_id, members, 12 | about=None, avatar=None): 13 | self.id = str(group_id) 14 | self.access_hash = str(access_hash) 15 | self.title = str(title) 16 | self.is_member = bool(is_member) 17 | self.creator_user_id = str(creator_user_id) 18 | 19 | if all(isinstance(member, GroupMember) for member in members): 20 | self.members = members 21 | else: 22 | raise ValueError(Error.unacceptable_object_type) 23 | 24 | self.about = str(about) if about else None 25 | 26 | if avatar: 27 | if isinstance(avatar, Avatar): 28 | self.avatar = avatar 29 | else: 30 | raise ValueError(Error.unacceptable_object_type) 31 | else: 32 | self.avatar = None 33 | 34 | def get_json_object(self): 35 | data = { 36 | "id": self.id, 37 | "accessHash": self.access_hash, 38 | "title": self.title, 39 | "isMember": self.is_member, 40 | "creatorUserId": self.creator_user_id, 41 | "members": self.members, 42 | "about": self.about, 43 | "avatar": self.avatar, 44 | } 45 | return data 46 | 47 | def get_json_str(self): 48 | return json_handler.dumps(self.get_json_object()) 49 | 50 | @classmethod 51 | def load_from_json(cls, json): 52 | if isinstance(json, dict): 53 | json_dict = json 54 | elif isinstance(json, str): 55 | json_dict = json_handler.loads(json) 56 | else: 57 | raise ValueError(Error.unacceptable_json) 58 | 59 | group_id = json_dict.get('id', None) 60 | access_hash = json_dict.get('accessHash', None) 61 | title = json_dict.get('title', None) 62 | is_member = json_dict.get('isMember', None) 63 | creator_user_id = json_dict.get('creatorUserId', None) 64 | members = [GroupMember.load_from_json(member) for member in json_dict.get('members', None)] 65 | 66 | if (not group_id) or (not access_hash) or (title is None) or (is_member is None) or ( 67 | not creator_user_id) or (members is None): 68 | raise ValueError(Error.none_or_invalid_attribute) 69 | 70 | about = json_dict.get('about', None) 71 | avatar = Avatar.load_from_json(json_dict.get('avatar', None)) if json_dict.get('avatar', None) else None 72 | 73 | return cls(group_id=group_id, access_hash=access_hash, is_member=is_member, creator_user_id=creator_user_id, 74 | members=members, title=title, about=about, avatar=avatar) 75 | -------------------------------------------------------------------------------- /balebot/models/base_models/group_member.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.jsonable import Jsonable 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class GroupMember(Jsonable): 8 | def __init__(self, user_id, invite_user_id, member_since, is_admin=None): 9 | self.user_id = str(user_id) 10 | self.invite_user_id = str(invite_user_id) 11 | self.member_since = str(member_since) 12 | self.is_admin = bool(is_admin) if is_admin else None 13 | 14 | def get_json_object(self): 15 | data = { 16 | "userId": self.user_id, 17 | "inviteUserId": self.invite_user_id, 18 | "memberSince": self.member_since, 19 | "isAdmin": self.is_admin, 20 | } 21 | 22 | return data 23 | 24 | def get_json_str(self): 25 | return json_handler.dumps(self.get_json_object()) 26 | 27 | @classmethod 28 | def load_from_json(cls, json): 29 | if isinstance(json, dict): 30 | json_dict = json 31 | elif isinstance(json, str): 32 | json_dict = json_handler.loads(json) 33 | else: 34 | raise ValueError(Error.unacceptable_json) 35 | 36 | user_id = json_dict.get('userId', None) 37 | invite_user_id = json_dict.get('inviteUserId', None) 38 | member_since = json_dict.get('memberSince', None) 39 | is_admin = json_dict.get('isAdmin', None) 40 | 41 | if (not user_id) or (not invite_user_id) or (member_since is None): 42 | raise ValueError(Error.none_or_invalid_attribute) 43 | 44 | return cls(user_id=user_id, invite_user_id=invite_user_id, member_since=member_since, is_admin=is_admin) 45 | -------------------------------------------------------------------------------- /balebot/models/base_models/group_peer.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.constants.peer_type import PeerType 4 | from .peer import Peer 5 | 6 | 7 | class GroupPeer(Peer): 8 | def __init__(self, peer_id, access_hash): 9 | super(GroupPeer, self).__init__(peer_type=PeerType.group, peer_id=peer_id, access_hash=access_hash) 10 | 11 | @classmethod 12 | def load_from_json(cls, json): 13 | if isinstance(json, dict): 14 | json_dict = json 15 | elif isinstance(json, str): 16 | json_dict = json_handler.loads(json) 17 | else: 18 | raise ValueError("json input has unacceptable format.") 19 | 20 | peer_type = json_dict.get('$type', None) 21 | peer_id = json_dict.get('id', None) 22 | access_hash = json_dict.get('accessHash', None) 23 | 24 | if (peer_type != PeerType.group) or (not peer_id) or (not access_hash): 25 | raise ValueError("peer_type , peer_id and access_hash should have correct values.") 26 | 27 | return cls(peer_id=peer_id, access_hash=access_hash) 28 | -------------------------------------------------------------------------------- /balebot/models/base_models/image_location.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.jsonable import Jsonable 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.base_models.file_location import FileLocation 7 | 8 | 9 | class ImageLocation(Jsonable): 10 | def __init__(self, width, height, file_size, file_location): 11 | self.width = int(width) 12 | self.height = int(height) 13 | self.file_size = int(file_size) 14 | if isinstance(file_location, FileLocation): 15 | self.file_location = file_location 16 | else: 17 | raise ValueError(Error.unacceptable_object_type) 18 | 19 | def get_json_object(self): 20 | data = { 21 | "width": self.width, 22 | "height": self.height, 23 | "fileSize": self.file_size, 24 | "fileLocation": self.file_location.get_json_object() 25 | } 26 | 27 | return data 28 | 29 | def get_json_str(self): 30 | return json_handler.dumps(self.get_json_object()) 31 | 32 | @classmethod 33 | def load_from_json(cls, json): 34 | if isinstance(json, dict): 35 | json_dict = json 36 | elif isinstance(json, str): 37 | json_dict = json_handler.loads(json) 38 | else: 39 | raise ValueError(Error.unacceptable_json) 40 | 41 | width = json_dict.get("width", None) 42 | height = json_dict.get("height", None) 43 | file_size = json_dict.get("fileSize", None) 44 | file_location = FileLocation.load_from_json(json_dict.get("fileLocation", None)) 45 | 46 | if (width is None) or (height is None) or (file_size is None) or (file_location is None): 47 | raise ValueError(Error.none_or_invalid_attribute) 48 | 49 | return cls(width=width, height=height, file_size=file_size, file_location=file_location) 50 | -------------------------------------------------------------------------------- /balebot/models/base_models/jsonable.py: -------------------------------------------------------------------------------- 1 | class Jsonable: 2 | def get_json_object(self): 3 | raise NotImplementedError 4 | 5 | def get_json_str(self): 6 | raise NotImplementedError 7 | 8 | @classmethod 9 | def load_from_json(cls, json): 10 | raise NotImplementedError 11 | -------------------------------------------------------------------------------- /balebot/models/base_models/member.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.jsonable import Jsonable 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class Member(Jsonable): 8 | def __init__(self, user_id, invite_user_id, date, is_admin=None): 9 | self.user_id = str(user_id) 10 | self.invite_user_id = str(invite_user_id) 11 | self.date = str(date) 12 | self.is_admin = bool(is_admin) if is_admin else None 13 | 14 | def get_json_object(self): 15 | data = { 16 | "userId": self.user_id, 17 | "inviteUserId": self.invite_user_id, 18 | "date": self.date, 19 | "isAdmin": self.is_admin, 20 | 21 | } 22 | 23 | return data 24 | 25 | def get_json_str(self): 26 | return json_handler.dumps(self.get_json_object()) 27 | 28 | @classmethod 29 | def load_from_json(cls, json): 30 | if isinstance(json, dict): 31 | json_dict = json 32 | elif isinstance(json, str): 33 | json_dict = json_handler.loads(json) 34 | else: 35 | raise ValueError(Error.unacceptable_json) 36 | 37 | user_id = json_dict.get('userId', None) 38 | invite_user_id = json_dict.get('inviteUserId', None) 39 | date = json_dict.get('date', None) 40 | is_admin = json_dict.get('isAdmin', None) 41 | 42 | if (not user_id) or (not invite_user_id) or (date is None): 43 | raise ValueError(Error.none_or_invalid_attribute) 44 | 45 | return cls(user_id=user_id, invite_user_id=invite_user_id, date=date, is_admin=is_admin) 46 | -------------------------------------------------------------------------------- /balebot/models/base_models/pack_info.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.jsonable import Jsonable 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class PackInfo(Jsonable): 8 | def __init__(self, pack_id, name): 9 | self.pack_id = str(pack_id) 10 | self.name = str(name) 11 | 12 | def get_json_object(self): 13 | data = { 14 | "id": self.pack_id, 15 | "name": self.name, 16 | } 17 | return data 18 | 19 | def get_json_str(self): 20 | return json_handler.dumps(self.get_json_object()) 21 | 22 | @classmethod 23 | def load_from_json(cls, json): 24 | if isinstance(json, dict): 25 | json_dict = json 26 | elif isinstance(json, str): 27 | json_dict = json_handler.loads(json) 28 | else: 29 | raise ValueError(Error.unacceptable_json) 30 | 31 | pack_id = json_dict.get('id', None) 32 | name = json_dict.get('name', None) 33 | 34 | if (not pack_id) or (name is None): 35 | raise ValueError(Error.none_or_invalid_attribute) 36 | 37 | return cls(pack_id=pack_id, name=name) 38 | -------------------------------------------------------------------------------- /balebot/models/base_models/peer.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.jsonable import Jsonable 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class Peer(Jsonable): 8 | def __init__(self, peer_type, peer_id, access_hash): 9 | self.type = str(peer_type) 10 | self.peer_id = str(peer_id) 11 | self.access_hash = str(access_hash) 12 | 13 | def get_json_object(self): 14 | data = { 15 | "$type": self.type, 16 | "id": self.peer_id, 17 | "accessHash": self.access_hash, 18 | } 19 | return data 20 | 21 | def get_json_str(self): 22 | return json_handler.dumps(self.get_json_object()) 23 | 24 | @classmethod 25 | def load_from_json(cls, json): 26 | if isinstance(json, dict): 27 | json_dict = json 28 | elif isinstance(json, str): 29 | json_dict = json_handler.loads(json) 30 | else: 31 | raise ValueError(Error.unacceptable_json) 32 | 33 | peer_type = json_dict.get('$type', None) 34 | peer_id = json_dict.get('id', None) 35 | access_hash = json_dict.get('accessHash', None) 36 | 37 | if (not peer_type) or (not peer_id) or (not access_hash): 38 | raise ValueError(Error.none_or_invalid_attribute) 39 | 40 | return cls(peer_type=peer_type, peer_id=peer_id, access_hash=access_hash) 41 | -------------------------------------------------------------------------------- /balebot/models/base_models/raw_json.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models.jsonable import Jsonable 2 | 3 | 4 | class RawJson(Jsonable): 5 | pass 6 | -------------------------------------------------------------------------------- /balebot/models/base_models/request.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.request_body import RequestBody 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.base_models.jsonable import Jsonable 7 | 8 | 9 | class Request(Jsonable): 10 | id_counter = 0 11 | 12 | def __init__(self, service, body): 13 | self._id = str(Request.id_counter) 14 | self.service = str(service) 15 | if isinstance(body, RequestBody): 16 | self.body = body 17 | else: 18 | raise ValueError(Error.unacceptable_object_type) 19 | 20 | Request.id_counter += 1 21 | 22 | def get_json_object(self): 23 | data = { 24 | "$type": "Request", 25 | "id": self._id, 26 | "service": self.service, 27 | "body": self.body.get_json_object(), 28 | } 29 | return data 30 | 31 | def get_json_str(self): 32 | return json_handler.dumps(self.get_json_object()) 33 | 34 | @classmethod 35 | def load_from_json(cls, json): 36 | pass 37 | 38 | @property 39 | def id(self): 40 | return self._id 41 | -------------------------------------------------------------------------------- /balebot/models/base_models/request_body.py: -------------------------------------------------------------------------------- 1 | 2 | from balebot.models.base_models.jsonable import Jsonable 3 | 4 | 5 | class RequestBody(Jsonable): 6 | @classmethod 7 | def load_from_json(cls, json): 8 | pass 9 | -------------------------------------------------------------------------------- /balebot/models/base_models/response.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | import traceback 3 | from importlib import import_module 4 | from balebot.models.constants.errors import Error 5 | from balebot.utils.logger import Logger 6 | 7 | from balebot.models.server_responses.bot_error_response import BotError 8 | from balebot.models.server_responses.bot_success_response import BotSuccess 9 | 10 | 11 | class Response: 12 | def __init__(self, json): 13 | self.logger = Logger.get_logger() 14 | 15 | if isinstance(json, dict): 16 | json_dict = json 17 | elif isinstance(json, str): 18 | json_dict = json_handler.loads(json) 19 | else: 20 | raise ValueError(Error.unacceptable_json) 21 | 22 | self._id = json_dict.get("id", None) 23 | self.body_json = json_dict.get("body", None) 24 | 25 | if self.body_json.get("tag", None): 26 | self.body = BotError(self.body_json) 27 | del self.body_json 28 | else: 29 | self.body = None 30 | 31 | def is_bot_error(self): 32 | return isinstance(self.body, BotError) 33 | 34 | def create_body(self, body_module_name, body_class_name): 35 | try: 36 | if self.body is None: 37 | if self.body_json.get("tag", None): 38 | self.body = BotError(self.body_json) 39 | elif not self.body_json: 40 | self.body = BotSuccess() 41 | else: 42 | module_obj = import_module(body_module_name) 43 | body_class = getattr(module_obj, body_class_name) 44 | self.body = body_class(self.body_json) 45 | del self.body_json 46 | 47 | except Exception as ex: 48 | self.logger.error(ex, extra={"tag": "err"}) 49 | traceback.print_exc() 50 | 51 | @property 52 | def id(self): 53 | return self._id 54 | 55 | def get_response(self): 56 | return self.body_json 57 | -------------------------------------------------------------------------------- /balebot/models/base_models/response_body.py: -------------------------------------------------------------------------------- 1 | class ResponseBody: 2 | pass 3 | -------------------------------------------------------------------------------- /balebot/models/base_models/user.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.avatar import Avatar 4 | from balebot.models.base_models.bot_command import BotCommand 5 | from balebot.models.base_models.contact_record import ContactRecord 6 | from balebot.models.constants.errors import Error 7 | 8 | from balebot.models.base_models.jsonable import Jsonable 9 | 10 | 11 | class User(Jsonable): 12 | def __init__(self, user_id, access_hash, name, contact_records, preferred_languages, bot_commands, 13 | sex=None, about=None, avatar=None, username=None, is_bot=None, time_zone=None): 14 | self.id = str(user_id) 15 | self.access_hash = str(access_hash) 16 | self.name = str(name) 17 | 18 | if all(isinstance(contact_record, ContactRecord) for contact_record in contact_records): 19 | self.contact_records = [ContactRecord(contact_record) for contact_record in contact_records] 20 | else: 21 | ValueError(Error.unacceptable_object_type) 22 | 23 | self.preferred_languages = list(preferred_languages) 24 | 25 | if all(isinstance(bot_command, BotCommand) for bot_command in bot_commands): 26 | self.bot_commands = bot_commands 27 | else: 28 | ValueError(Error.unacceptable_object_type) 29 | 30 | self.sex = int(sex) if sex else None 31 | self.about = str(about) if about else None 32 | 33 | if avatar: 34 | if isinstance(avatar, Avatar): 35 | self.avatar = avatar 36 | else: 37 | raise ValueError(Error.unacceptable_object_type) 38 | else: 39 | self.avatar = None 40 | 41 | self.username = str(username) if username else None 42 | self.is_bot = bool(is_bot) if is_bot else None 43 | self.time_zone = str(time_zone) if time_zone else None 44 | 45 | def get_json_object(self): 46 | 47 | data = { 48 | "id": self.id, 49 | "accessHash": self.access_hash, 50 | "name": self.name, 51 | "contactRecords": self.contact_records, 52 | "preferredLanguages": self.preferred_languages, 53 | "botCommands": self.bot_commands, 54 | "sex": self.sex, 55 | "about": self.about, 56 | "avatar": self.avatar, 57 | "username": self.username, 58 | "isBot": self.is_bot, 59 | "timeZone": self.time_zone, 60 | 61 | } 62 | return data 63 | 64 | def get_json_str(self): 65 | return json_handler.dumps(self.get_json_object()) 66 | 67 | @classmethod 68 | def load_from_json(cls, json): 69 | if isinstance(json, dict): 70 | json_dict = json 71 | elif isinstance(json, str): 72 | json_dict = json_handler.loads(json) 73 | else: 74 | raise ValueError(Error.unacceptable_json) 75 | 76 | user_id = json_dict.get('id', None) 77 | access_hash = json_dict.get('accessHash', None) 78 | name = json_dict.get('name', None) 79 | contact_records = [ContactRecord(contact_record) for contact_record in json_dict.get('contactRecords', None)] 80 | preferred_languages = list(json_dict.get('preferredLanguages', None)) 81 | bot_commands = [BotCommand.load_from_json(bot_command) for bot_command in json_dict.get('botCommands', None)] 82 | 83 | if (not user_id) or (not access_hash) or (name is None) or (contact_records is None) or ( 84 | preferred_languages is None) or (bot_commands is None): 85 | raise ValueError(Error.none_or_invalid_attribute) 86 | 87 | sex = json_dict.get('sex', None) 88 | about = json_dict.get('about', None) 89 | avatar = Avatar.load_from_json(json_dict.get('avatar', None)) if json_dict.get('avatar', None) else None 90 | username = json_dict.get('username', None) 91 | is_bot = json_dict.get('is_bot', None) 92 | time_zone = json_dict.get('timeZone', None) 93 | 94 | return cls(user_id=user_id, access_hash=access_hash, contact_records=contact_records, 95 | preferred_languages=preferred_languages, bot_commands=bot_commands, name=name, sex=sex, 96 | about=about, avatar=avatar, username=username, is_bot=is_bot, time_zone=time_zone) 97 | -------------------------------------------------------------------------------- /balebot/models/base_models/user_peer.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.constants.peer_type import PeerType 4 | from balebot.models.constants.errors import Error 5 | 6 | from .peer import Peer 7 | 8 | 9 | class UserPeer(Peer): 10 | def __init__(self, peer_id, access_hash): 11 | super(UserPeer, self).__init__(peer_type=PeerType.user, peer_id=peer_id, access_hash=access_hash) 12 | 13 | @classmethod 14 | def load_from_json(cls, json): 15 | if isinstance(json, dict): 16 | json_dict = json 17 | elif isinstance(json, str): 18 | json_dict = json_handler.loads(json) 19 | else: 20 | raise ValueError(Error.unacceptable_json) 21 | 22 | peer_type = json_dict.get('$type', None) 23 | peer_id = json_dict.get('id', None) 24 | access_hash = json_dict.get('accessHash', None) 25 | 26 | if (peer_type != PeerType.user) or (not peer_id) or (not access_hash): 27 | raise ValueError(Error.none_or_invalid_attribute) 28 | 29 | return cls(peer_id=peer_id, access_hash=access_hash, ) 30 | -------------------------------------------------------------------------------- /balebot/models/base_models/value_types/__init__.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models.value_types.map_value import MapValue 2 | from balebot.models.base_models.value_types.map_value_item import MapValueItem 3 | from balebot.models.base_models.value_types.raw_value import RawValue 4 | from balebot.models.base_models.value_types.string_val import StringVal 5 | from balebot.models.base_models.value_types.array_val import ArrayVal 6 | from balebot.models.base_models.value_types.boolean_value import BooleanValue 7 | from balebot.models.base_models.value_types.double_val import DoubleVal 8 | from balebot.models.base_models.value_types.int32_val import Int32Val 9 | from balebot.models.base_models.value_types.int64_val import Int64Val 10 | -------------------------------------------------------------------------------- /balebot/models/base_models/value_types/array_val.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.value_types.raw_value import RawValue 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.value_type import ValueType 7 | from balebot.models.factories import raw_value_factory 8 | 9 | 10 | class ArrayVal(RawValue): 11 | def __init__(self, value): 12 | if all(isinstance(item, RawValue) for item in value): 13 | self.values = value 14 | else: 15 | raise ValueError(Error.unacceptable_object_type) 16 | 17 | def get_json_object(self): 18 | data = { 19 | "$type": ValueType.array_val, 20 | "value": [value.get_json_object() for value in self.values], 21 | 22 | } 23 | return data 24 | 25 | def get_json_str(self): 26 | return json_handler.dumps(self.get_json_object()) 27 | 28 | @classmethod 29 | def load_from_json(cls, json): 30 | if isinstance(json, dict): 31 | json_dict = json 32 | elif isinstance(json, str): 33 | json_dict = json_handler.loads(json) 34 | else: 35 | raise ValueError(Error.unacceptable_json) 36 | 37 | temp_values = json_dict.get('value', None) 38 | items = [raw_value_factory.RawValueFactory.create_raw_value(value) for value in temp_values] 39 | 40 | return cls(items=items) 41 | -------------------------------------------------------------------------------- /balebot/models/base_models/value_types/boolean_value.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.value_types.raw_value import RawValue 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.value_type import ValueType 7 | 8 | 9 | class BooleanValue(RawValue): 10 | def __init__(self, value): 11 | self.value = bool(value) 12 | 13 | def get_json_object(self): 14 | data = { 15 | "$type": ValueType.boolean_value, 16 | "value": self.value, 17 | 18 | } 19 | return data 20 | 21 | def get_json_str(self): 22 | return json_handler.dumps(self.get_json_object()) 23 | 24 | @classmethod 25 | def load_from_json(cls, json): 26 | if isinstance(json, dict): 27 | json_dict = json 28 | elif isinstance(json, str): 29 | json_dict = json_handler.loads(json) 30 | else: 31 | raise ValueError(Error.unacceptable_json) 32 | 33 | value = json_dict.get('value', None) 34 | 35 | return cls(value=value) 36 | -------------------------------------------------------------------------------- /balebot/models/base_models/value_types/double_val.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.value_types.raw_value import RawValue 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.value_type import ValueType 7 | 8 | 9 | class DoubleVal(RawValue): 10 | def __init__(self, value): 11 | self.value = float(value) 12 | 13 | def get_json_object(self): 14 | data = { 15 | "$type": ValueType.double_val, 16 | "value": self.value, 17 | 18 | } 19 | return data 20 | 21 | def get_json_str(self): 22 | return json_handler.dumps(self.get_json_object()) 23 | 24 | @classmethod 25 | def load_from_json(cls, json): 26 | if isinstance(json, dict): 27 | json_dict = json 28 | elif isinstance(json, str): 29 | json_dict = json_handler.loads(json) 30 | else: 31 | raise ValueError(Error.unacceptable_json) 32 | 33 | value = json_dict.get('value', None) 34 | 35 | return cls(value=value) 36 | -------------------------------------------------------------------------------- /balebot/models/base_models/value_types/int32_val.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.value_types.raw_value import RawValue 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.value_type import ValueType 7 | 8 | 9 | class Int32Val(RawValue): 10 | def __init__(self, value): 11 | self.value = int(value) 12 | 13 | def get_json_object(self): 14 | data = { 15 | "$type": ValueType.int32_val, 16 | "value": self.value, 17 | 18 | } 19 | return data 20 | 21 | def get_json_str(self): 22 | return json_handler.dumps(self.get_json_object()) 23 | 24 | @classmethod 25 | def load_from_json(cls, json): 26 | if isinstance(json, dict): 27 | json_dict = json 28 | elif isinstance(json, str): 29 | json_dict = json_handler.loads(json) 30 | else: 31 | raise ValueError(Error.unacceptable_json) 32 | 33 | value = json_dict.get('value', None) 34 | 35 | return cls(value=value) 36 | -------------------------------------------------------------------------------- /balebot/models/base_models/value_types/int64_val.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.value_types.raw_value import RawValue 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.value_type import ValueType 7 | 8 | 9 | class Int64Val(RawValue): 10 | def __init__(self, value): 11 | self.value = str(value) 12 | 13 | def get_json_object(self): 14 | data = { 15 | "$type": ValueType.int64_val, 16 | "value": self.value, 17 | 18 | } 19 | return data 20 | 21 | def get_json_str(self): 22 | return json_handler.dumps(self.get_json_object()) 23 | 24 | @classmethod 25 | def load_from_json(cls, json): 26 | if isinstance(json, dict): 27 | json_dict = json 28 | elif isinstance(json, str): 29 | json_dict = json_handler.loads(json) 30 | else: 31 | raise ValueError(Error.unacceptable_json) 32 | 33 | value = json_dict.get('value', None) 34 | 35 | return cls(value=value) 36 | -------------------------------------------------------------------------------- /balebot/models/base_models/value_types/map_value.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.value_types.map_value_item import MapValueItem 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.base_models.value_types.raw_value import RawValue 7 | 8 | 9 | class MapValue(RawValue): 10 | def __init__(self, items): 11 | 12 | if isinstance(items, dict) and all(isinstance(value, RawValue) for key, value in items): 13 | 14 | items_list = [] 15 | for key, value in items: 16 | temp_dict = { 17 | "key": str(key), 18 | "value": value, 19 | } 20 | items_list.append(MapValueItem.load_from_json(temp_dict)) 21 | 22 | self.items = items_list 23 | 24 | elif all(isinstance(item, MapValueItem) for item in items): 25 | 26 | self.items = items 27 | else: 28 | raise ValueError(Error.unacceptable_object_type) 29 | 30 | def get_json_object(self): 31 | 32 | data = { 33 | "$type": "MapValue", 34 | "items": [item.get_json_object() for item in self.items], 35 | 36 | } 37 | 38 | return data 39 | 40 | def get_json_str(self): 41 | return json_handler.dumps(self.get_json_object()) 42 | 43 | @classmethod 44 | def load_from_json(cls, json): 45 | if isinstance(json, dict): 46 | json_dict = json 47 | elif isinstance(json, str): 48 | json_dict = json_handler.loads(json) 49 | else: 50 | raise ValueError(Error.unacceptable_json) 51 | 52 | temp_items = json_dict.get('items', None) 53 | items = [MapValueItem.load_from_json(item) for item in temp_items] 54 | 55 | return cls(items=items) 56 | 57 | def find_value(self, key): 58 | for item in self.items: 59 | if item.key == key: 60 | return item.value 61 | return 62 | -------------------------------------------------------------------------------- /balebot/models/base_models/value_types/map_value_item.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.value_types.raw_value import RawValue 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.factories import raw_value_factory 7 | 8 | 9 | class MapValueItem: 10 | def __init__(self, key, value): 11 | if isinstance(value, RawValue): 12 | self.value = value 13 | else: 14 | raise ValueError(Error.unacceptable_object_type) 15 | self.key = str(key) 16 | 17 | def get_json_object(self): 18 | 19 | data = { 20 | "key": self.key, 21 | "value": self.value.get_json_object(), 22 | } 23 | return data 24 | 25 | def get_json_str(self): 26 | return json_handler.dumps(self.get_json_object()) 27 | 28 | @classmethod 29 | def load_from_json(cls, json): 30 | if isinstance(json, dict): 31 | json_dict = json 32 | elif isinstance(json, str): 33 | json_dict = json_handler.loads(json) 34 | else: 35 | raise ValueError(Error.unacceptable_json) 36 | 37 | key = json_dict.get('key', None) 38 | 39 | tmp_value = json_dict.get('value', None) 40 | value = raw_value_factory.RawValueFactory.create_raw_value(tmp_value) 41 | 42 | if (key is None) or (value is None): 43 | raise ValueError(Error.none_or_invalid_attribute) 44 | 45 | return cls(key=key, value=value) 46 | -------------------------------------------------------------------------------- /balebot/models/base_models/value_types/raw_value.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models.jsonable import Jsonable 2 | 3 | 4 | class RawValue(Jsonable): 5 | pass 6 | -------------------------------------------------------------------------------- /balebot/models/base_models/value_types/string_val.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.value_types.raw_value import RawValue 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.value_type import ValueType 7 | 8 | 9 | class StringVal(RawValue): 10 | def __init__(self, text): 11 | self.text = str(text) 12 | 13 | def get_json_object(self): 14 | data = { 15 | "$type": ValueType.string_val, 16 | "text": self.text, 17 | 18 | } 19 | 20 | return data 21 | 22 | def get_json_str(self): 23 | return json_handler.dumps(self.get_json_object()) 24 | 25 | @classmethod 26 | def load_from_json(cls, json): 27 | if isinstance(json, dict): 28 | json_dict = json 29 | elif isinstance(json, str): 30 | json_dict = json_handler.loads(json) 31 | else: 32 | raise ValueError(Error.unacceptable_json) 33 | 34 | text = json_dict.get('text', None) 35 | 36 | return cls(text=text) 37 | -------------------------------------------------------------------------------- /balebot/models/client_requests/__init__.py: -------------------------------------------------------------------------------- 1 | from balebot.models.client_requests.files.get_file_download_url import GetFileDownloadUrl 2 | from balebot.models.client_requests.files.get_file_upload_url import GetFileUploadUrl 3 | 4 | from balebot.models.client_requests.group.create_group import CreateGroup 5 | from balebot.models.client_requests.group.get_group_api_struct import GetGroupApiStruct 6 | from balebot.models.client_requests.group.invite_user import InviteUser 7 | 8 | from balebot.models.client_requests.messaging.send_message import SendMessage 9 | from balebot.models.client_requests.messaging.edit_message import EditMessage 10 | 11 | from balebot.models.client_requests.sequence.get_difference import GetDifference 12 | -------------------------------------------------------------------------------- /balebot/models/client_requests/files/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/client_requests/files/__init__.py -------------------------------------------------------------------------------- /balebot/models/client_requests/files/get_file_download_url.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.request_body import RequestBody 4 | from balebot.models.constants.request_type import RequestType 5 | 6 | 7 | class GetFileDownloadUrl(RequestBody): 8 | def __init__(self, file_id, user_id, file_type, file_version=1, is_server=False, is_resume_upload=False): 9 | self.file_id = str(file_id) 10 | self.user_id = str(user_id) 11 | self.file_version = int(file_version) 12 | self.is_server = bool(is_server) 13 | self.is_resume_upload = bool(is_resume_upload) 14 | 15 | # it can be "photo" or "file" 16 | self.file_type = str(file_type) 17 | 18 | def get_json_object(self): 19 | data = { 20 | "$type": RequestType.get_file_download_url, 21 | "fileId": self.file_id, 22 | "userId": self.user_id, 23 | "fileVersion": self.file_version, 24 | "isServer": self.is_server, 25 | "isResumeUpload": self.is_resume_upload, 26 | 'fileType': self.file_type, 27 | } 28 | 29 | return data 30 | 31 | def get_json_str(self): 32 | return json_handler.dumps(self.get_json_object()) 33 | -------------------------------------------------------------------------------- /balebot/models/client_requests/files/get_file_upload_url.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.request_body import RequestBody 4 | from balebot.models.constants.request_type import RequestType 5 | 6 | 7 | class GetFileUploadUrl(RequestBody): 8 | def __init__(self, size, crc, file_type, is_server=False): 9 | self.size = int(size) 10 | self.crc = str(crc) 11 | self.is_server = bool(is_server) 12 | 13 | # it can be "photo" or "file" 14 | self.file_type = str(file_type) 15 | 16 | def get_json_object(self): 17 | data = { 18 | "$type": RequestType.get_file_upload_url, 19 | "size": self.size, 20 | "crc": self.crc, 21 | "isServer": self.is_server, 22 | 'fileType': self.file_type, 23 | } 24 | 25 | return data 26 | 27 | def get_json_str(self): 28 | return json_handler.dumps(self.get_json_object()) 29 | -------------------------------------------------------------------------------- /balebot/models/client_requests/group/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/client_requests/group/__init__.py -------------------------------------------------------------------------------- /balebot/models/client_requests/group/create_group.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.request_body import RequestBody 4 | from balebot.models.constants.request_type import RequestType 5 | 6 | 7 | class CreateGroup(RequestBody): 8 | def __init__(self, title): 9 | self.title = str(title) 10 | 11 | def get_json_object(self): 12 | data = { 13 | "$type": RequestType.create_group, 14 | "title": self.title, 15 | } 16 | 17 | return data 18 | 19 | def get_json_str(self): 20 | return json_handler.dumps(self.get_json_object()) 21 | -------------------------------------------------------------------------------- /balebot/models/client_requests/group/get_group_api_struct.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.request_body import RequestBody 4 | from balebot.models.constants.request_type import RequestType 5 | 6 | 7 | class GetGroupApiStruct(RequestBody): 8 | def __init__(self, group_id, client_user_id): 9 | self.group_id = str(group_id) 10 | self.client_user_id = str(client_user_id) 11 | 12 | def get_json_object(self): 13 | data = { 14 | "$type": RequestType.get_group_api_struct, 15 | "groupId": self.group_id, 16 | "clientUserId": self.client_user_id, 17 | 18 | } 19 | 20 | return data 21 | 22 | def get_json_str(self): 23 | return json_handler.dumps(self.get_json_object()) 24 | -------------------------------------------------------------------------------- /balebot/models/client_requests/group/invite_user.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.group_peer import GroupPeer 4 | from balebot.models.base_models.user_peer import UserPeer 5 | 6 | from balebot.models.base_models.request_body import RequestBody 7 | from balebot.models.constants.request_type import RequestType 8 | 9 | 10 | class InviteUser(RequestBody): 11 | def __init__(self, group_peer, user_peer): 12 | if isinstance(group_peer, GroupPeer): 13 | self.group_peer = group_peer 14 | 15 | if isinstance(user_peer, UserPeer): 16 | self.user_peer = user_peer 17 | 18 | def get_json_object(self): 19 | data = { 20 | "$type": RequestType.invite_user, 21 | "groupPeer": self.group_peer.get_json_object(), 22 | "userPeer": self.user_peer.get_json_object(), 23 | } 24 | 25 | return data 26 | 27 | def get_json_str(self): 28 | return json_handler.dumps(self.get_json_object()) 29 | -------------------------------------------------------------------------------- /balebot/models/client_requests/messaging/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/client_requests/messaging/__init__.py -------------------------------------------------------------------------------- /balebot/models/client_requests/messaging/edit_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.peer import Peer 4 | from balebot.models.base_models.request_body import RequestBody 5 | from balebot.models.constants.errors import Error 6 | from balebot.models.constants.request_type import RequestType 7 | from balebot.models.messages.base_message import BaseMessage 8 | from balebot.utils.util_functions import generate_random_id 9 | 10 | 11 | class EditMessage(RequestBody): 12 | def __init__(self, updated_message, peer, random_id): 13 | if isinstance(updated_message, BaseMessage) and isinstance(peer, Peer): 14 | self.updated_message = updated_message 15 | self.peer = peer 16 | self._random_id = str(random_id) 17 | 18 | else: 19 | raise ValueError(Error.unacceptable_object_type) 20 | 21 | def get_json_object(self): 22 | 23 | data = { 24 | "$type": RequestType.edit_message, 25 | "peer": self.peer.get_json_object(), 26 | "randomId": self._random_id, 27 | "message": self.updated_message.get_json_object() 28 | } 29 | 30 | return data 31 | 32 | def get_json_str(self): 33 | return json_handler.dumps(self.get_json_object()) 34 | -------------------------------------------------------------------------------- /balebot/models/client_requests/messaging/send_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.bot_quoted_message import BotQuotedMessage 4 | from balebot.models.base_models.peer import Peer 5 | from balebot.models.base_models.request_body import RequestBody 6 | from balebot.models.constants.errors import Error 7 | from balebot.models.constants.request_type import RequestType 8 | from balebot.models.messages.base_message import BaseMessage 9 | from balebot.utils.util_functions import generate_random_id 10 | 11 | 12 | class SendMessage(RequestBody): 13 | def __init__(self, message, receiver_user, quoted_message=None, random_id=None): 14 | 15 | if isinstance(message, BaseMessage) and ( 16 | isinstance(receiver_user, Peer) or isinstance(receiver_user, str)) and ( 17 | isinstance(quoted_message, BotQuotedMessage) or not quoted_message): 18 | 19 | self.message = message 20 | self.receiver_user = receiver_user 21 | self.quoted_message = quoted_message 22 | 23 | if random_id: 24 | self._random_id = str(random_id) 25 | else: 26 | self._random_id = str(generate_random_id()) 27 | 28 | else: 29 | raise ValueError(Error.unacceptable_object_type) 30 | 31 | def get_json_object(self): 32 | 33 | data = { 34 | "$type": RequestType.send_message, 35 | "randomId": self._random_id, 36 | "message": self.message.get_json_object(), 37 | "quotedMessage": self.quoted_message.get_json_object() if self.quoted_message else None, 38 | } 39 | if isinstance(self.receiver_user, Peer): 40 | data["peer"] = self.receiver_user.get_json_object() 41 | else: 42 | data["nickName"] = self.receiver_user 43 | 44 | return data 45 | 46 | def get_json_str(self): 47 | return json_handler.dumps(self.get_json_object()) -------------------------------------------------------------------------------- /balebot/models/client_requests/sequence/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/client_requests/sequence/__init__.py -------------------------------------------------------------------------------- /balebot/models/client_requests/sequence/get_difference.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.request_body import RequestBody 4 | from balebot.models.constants.request_type import RequestType 5 | 6 | 7 | class GetDifference(RequestBody): 8 | def __init__(self, seq, how_many): 9 | self.seq = int(seq) if seq else 0 10 | self.how_many = how_many 11 | 12 | def get_json_object(self): 13 | data = { 14 | "$type": RequestType.get_difference, 15 | "seq": self.seq, 16 | "howMany": self.how_many, 17 | } 18 | 19 | return data 20 | 21 | def get_json_str(self): 22 | return json_handler.dumps(self.get_json_object()) 23 | -------------------------------------------------------------------------------- /balebot/models/client_requests/sequence/get_last_sequence.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.request_body import RequestBody 4 | from balebot.models.constants.request_type import RequestType 5 | 6 | 7 | class GetLastSequence(RequestBody): 8 | def __init__(self): 9 | self.seq = "input" 10 | 11 | def get_json_object(self): 12 | data = { 13 | "$type": RequestType.get_last_seq, 14 | "seq": self.seq 15 | } 16 | return data 17 | 18 | def get_json_str(self): 19 | return json_handler.dumps(self.get_json_object()) 20 | -------------------------------------------------------------------------------- /balebot/models/constants/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/constants/__init__.py -------------------------------------------------------------------------------- /balebot/models/constants/bank_ext_types.py: -------------------------------------------------------------------------------- 1 | class BankExtTypes: 2 | bank_money_transfer = "BankMoneyTransfer" 3 | bank_remain = "BankRemain" 4 | bank_transaction = "BankTransaction" 5 | deprecated_receipt = "DeprecatedReceipt" 6 | deprecated_receipt_message = "DepricatedReceiptMessage" 7 | receipt_message = "ReceiptMessage" 8 | -------------------------------------------------------------------------------- /balebot/models/constants/default_purchase_message_photo.py: -------------------------------------------------------------------------------- 1 | class DefaultPhoto: 2 | file_id = '4813274878314219265' 3 | access_hash = '1471278867' 4 | name = "purchase.jpg" 5 | file_size = '41430' 6 | mime_type = 'image/jpeg' 7 | thumb = "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA4KCw0LCQ4NDA0QDw4RFiQXFhQUFiwgIRokNC43NjMuMjI6QVNGOj1OPjIySGJJTlZYXV5dOEVmbWVabFNbXVn/2wBDAQ8QEBYTFioXFypZOzI7WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVn/wAARCABaAFoDASIAAhEBAxEB/8QAGgABAQEBAQEBAAAAAAAAAAAAAAQFAwIBB//EADwQAAEEAQEEBAkKBwAAAAAAAAEAAgMEEQUSEyExNUFhsRQVIjJCUXFzkSNkdIGCk6GyweEkJVNjcqKj/8QAFwEBAQEBAAAAAAAAAAAAAAAAAAIBA//EACcRAQACAQEGBwEBAAAAAAAAAAEAAhESAxMhMUFRIjJCcYGRsSOh/9oADAMBAAIRAxEAPwD9DREVSIRESIRESIRESIRESIRESIRT3+j7PundxUFPS4zUhkjnswl8bXOEcmASQrKiZWc7WS2Amuiz/Ffz6999+y8jRarnbUxmnPrkkJ7kxXvGq/b/AGWSWq8Ti2SeJjh1OeAVIdapnAidJM8nAZGw5PxXaLTKUQw2tGf8htd6qa0NaGtAaByAHJPAR/R7Ez/GFmRxEGnTEDmZSI+9A/VpMkRVYh1Ne4k/EcFZPLHFGd5M2Ha4BziBg/WseWaoHHfatZfIBx3Rw0+zAx+Kupq5H6znd087fhPd06nWqPsPtxgtx5DIwRxOOZW0sia4yxVEPi+5KwgAbTSAfV5WV38L1DHDTf8Au1LVU5Y+iKWBeK/bNBFPRs+GU459jY28+TnOMEj9FQuKI4Z3ETJJ7/R9n3Tu4pQ6Pre6b3BL/R9n3Tu4pQ6Pre6b3BX6PmR6/iRRWNRsS2Nx4LsRyujG8Ds8PYuv83+Y/wC6+aT5176U9aKq9sOAkUq2rlWZ251SR3l2oIR/bZtd6eLZXkmfULLif6Z2B8Foqe1ZMO7ZGwSTSnZY3OPaT2BYXsuCU0qGbfrOEWkUYiCIA4jreS7P1clZFFHC3ZijZGDxw1oCidYuVQJLbYHQ8A8xZyztweYWgss26uZtCvQxIpLFzeuZFRywHAe6UAHtxzVMBmMf8QGB+fQJI/FdEUrk5SiqOczP0PoiD7X5itBZ+h9EQfa/MVoKtp533k7LyV9iT3+j7PundxXjTZopKMDWSMc5sTQ4BwJHAc1XzXCKpXhl3sULI37Ozloxw9iwTThmtXVkkuk+de+lPWis7SfOvfSnr06rfLiRqOyCeA3DeCq4NnjIopQwZl6juxyCWCzG0yGAnLBzc0jjjtVEDJGQtbLLvXjm/Z2c/UuigcM6JqJnWJ5LkJrwQzMMow58kZaGN6+fM9gWiotOlfKbe8cXbNhzW56gMYC9Wrza8oj3E8riNr5Jm1hUjnSSKoGpZWizheuSZMWmv2eovkDD8CgOrvbnZpx56jtEj4cE3b1Zu8Og/U+6H0RB9r8xWgptPrGpSjgc4Oc3OSO05/VUrLubKTdmJQHtCIimXIJNKgfM6WN80EjiS4xPxklfPFfz6999+y0EV7y3ec91TtM12kRvI3tm3IB6L5cjuVdux4LDvd257ARt49EdZXdfCAQQRkHmCs1L5ppQB08Jj0rscTp2sBlfNbdsNYeY4Zd7MLZUlPTq9J8joWnaeeZOcD1DsVa3aNV8MnZVsHihERROsIiJEIiJEIiJEIiJEIiJEIiJEIiJE//Z" 8 | width = 90 9 | height = 90 10 | ext_width = 1110 11 | ext_height = 1110 12 | -------------------------------------------------------------------------------- /balebot/models/constants/document_type.py: -------------------------------------------------------------------------------- 1 | class DocumentType: 2 | voice_document = 'Voice' 3 | video_document = 'Video' 4 | photo_document = 'Photo' 5 | -------------------------------------------------------------------------------- /balebot/models/constants/errors.py: -------------------------------------------------------------------------------- 1 | class Error: 2 | none_or_invalid_attribute = "main attributes should have value." 3 | unacceptable_json = "json input has unacceptable format." 4 | unacceptable_object_type = "object has unacceptable type" 5 | -------------------------------------------------------------------------------- /balebot/models/constants/file_type.py: -------------------------------------------------------------------------------- 1 | class FileType: 2 | photo = "photo" 3 | file = "file" 4 | -------------------------------------------------------------------------------- /balebot/models/constants/message_type.py: -------------------------------------------------------------------------------- 1 | class MessageType: 2 | text_message = 'Text' 3 | sticker_message = 'Sticker' 4 | template_message = 'TemplateMessage' 5 | purchase_message = 'PurchaseMessage' 6 | bank_message = 'BankMessage' 7 | order_message = 'OrderMessage' 8 | unsupported_message = 'Unsupported' 9 | json_message = 'Json' 10 | document_message = 'Document' 11 | template_response_message = 'TemplateMessageResponse' 12 | location_message = 'location' 13 | contact_message = 'contact' 14 | -------------------------------------------------------------------------------- /balebot/models/constants/peer_type.py: -------------------------------------------------------------------------------- 1 | class PeerType: 2 | user = "User" 3 | group = "Group" 4 | -------------------------------------------------------------------------------- /balebot/models/constants/raw_json_type.py: -------------------------------------------------------------------------------- 1 | class RawJsonType: 2 | location = "location" 3 | contact = "contact" 4 | -------------------------------------------------------------------------------- /balebot/models/constants/receipt_type.py: -------------------------------------------------------------------------------- 1 | class ReceiptType: 2 | purchese = "PURCHESE" 3 | bill = "BILL" 4 | charge = "CHARGE" 5 | money_transfer = "MONEY_TRANSFER" 6 | -------------------------------------------------------------------------------- /balebot/models/constants/request_to_response_mapper.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models.request_body import RequestBody 2 | 3 | 4 | class RequestToResponseMapper: 5 | request_response_map = { 6 | "GetFileDownloadUrl": ( 7 | "balebot.models.server_responses.files.response_get_download_url", "ResponseGetDownloadUrl"), 8 | "GetFileUploadUrl": ("balebot.models.server_responses.files.response_get_upload_url", "ResponseGetUploadUrl"), 9 | 10 | "CreateGroup": ("balebot.models.server_responses.group.response_create_group", "ResponseCreateGroup"), 11 | "GetGroupApiStruct": ("balebot.models.server_responses.group.get_group_api_response", "GetGroupApiResponse"), 12 | "InviteUser": ("balebot.models.server_responses.bot_success_response", "BotSuccess"), 13 | 14 | "SendMessage": ("balebot.models.server_responses.messaging.message_sent", "MessageSent"), 15 | "EditMessage": ( 16 | "balebot.models.server_responses.messaging.message_edited", "MessageEdited"), 17 | 18 | "GetDifference": ("balebot.models.server_responses.sequence.difference_update", "DifferenceUpdate"), 19 | "GetLastSequence": ("balebot.models.server_responses.sequence.get_last_seq_response", "GetLastSeqResponse"), 20 | 21 | } 22 | 23 | @classmethod 24 | def get_response(cls, request): 25 | if isinstance(request, RequestBody): 26 | request_class_name = request.__class__.__name__ 27 | return cls.request_response_map[str(request_class_name)] 28 | else: 29 | return cls.request_response_map[str(request)] 30 | -------------------------------------------------------------------------------- /balebot/models/constants/request_type.py: -------------------------------------------------------------------------------- 1 | class RequestType: 2 | get_file_download_url = "GetFileDownloadUrl" 3 | get_file_upload_url = "GetFileUploadUrl" 4 | 5 | create_group = "CreateGroup" 6 | get_group_api_struct = "GetGroupApiStruct" 7 | invite_user = "InviteUser" 8 | 9 | send_message = "SendMessage" 10 | edit_message = "EditMessage" 11 | 12 | get_difference = "GetDifference" 13 | get_last_seq = "GetLastSeq" 14 | -------------------------------------------------------------------------------- /balebot/models/constants/service_type.py: -------------------------------------------------------------------------------- 1 | class ServiceType: 2 | Messaging = 'messaging' 3 | Files = 'files' 4 | Stickers = 'stickers' 5 | Users = 'users' 6 | KeyValue = 'keyvalue' 7 | Bots = 'bots' 8 | WebHooks = 'webhooks' 9 | Monitor = 'monitor' 10 | Groups = "groups" 11 | SequenceUpdate = "sequence-update" 12 | banks = "banks" 13 | -------------------------------------------------------------------------------- /balebot/models/constants/template_button_action_type.py: -------------------------------------------------------------------------------- 1 | class ButtonAction: 2 | default = 1 3 | browse_user = 21 4 | barcode_reader = 22 5 | location = 23 6 | contact = 24 7 | __date = 25 8 | __time = 26 9 | photo = 27 10 | file = 28 11 | -------------------------------------------------------------------------------- /balebot/models/constants/update_body_type.py: -------------------------------------------------------------------------------- 1 | class UpdateBodyType: 2 | bot_read_update = "BotReadUpdate" 3 | bot_received_update = "BotReceivedUpdate" 4 | message = "Message" 5 | raw_update = "RawUpdate" 6 | -------------------------------------------------------------------------------- /balebot/models/constants/value_type.py: -------------------------------------------------------------------------------- 1 | class ValueType: 2 | string_val = "StringVal" 3 | int32_val = "Int32Val" 4 | int64_val = "Int64Val" 5 | double_val = "DoubleVal" 6 | array_val = "ArrayVal" 7 | map_value = "MapValue" 8 | boolean_value = "BooleanValue" 9 | -------------------------------------------------------------------------------- /balebot/models/factories/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/factories/__init__.py -------------------------------------------------------------------------------- /balebot/models/factories/bank_ext_factory.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models.banking import deprecated_receipt 2 | from balebot.models.base_models.banking import deprecated_receipt_message 3 | from balebot.models.base_models.banking import receipt_message 4 | from balebot.models.constants.bank_ext_types import BankExtTypes 5 | 6 | 7 | class BankExtFactory: 8 | @staticmethod 9 | def create_bank_ext(json_dict): 10 | bank_ext_type = json_dict.get("$type", None) 11 | 12 | if bank_ext_type == BankExtTypes.deprecated_receipt_message: 13 | return deprecated_receipt_message.DeprecatedReceiptMessage.load_from_json(json_dict) 14 | 15 | elif bank_ext_type == BankExtTypes.deprecated_receipt: 16 | return deprecated_receipt.DeprecatedReceipt.load_from_json(json_dict) 17 | 18 | elif bank_ext_type == BankExtTypes.receipt_message: 19 | return receipt_message.ReceiptMessage.load_from_json(json_dict) 20 | 21 | else: 22 | return None 23 | -------------------------------------------------------------------------------- /balebot/models/factories/message_factory.py: -------------------------------------------------------------------------------- 1 | from balebot.models.constants.message_type import MessageType 2 | from balebot.models.messages.banking import bank_message 3 | from balebot.models.messages.banking import purchase_message 4 | from balebot.models.messages import document_message 5 | from balebot.models.messages import location_message 6 | from balebot.models.messages import contact_message 7 | from balebot.models.messages import photo_message 8 | from balebot.models.messages import sticker_message 9 | from balebot.models.messages.template import template_message 10 | from balebot.models.messages import text_message 11 | from balebot.models.messages import unsupported_message 12 | from balebot.models.messages import json_message 13 | from balebot.models.messages import video_message 14 | from balebot.models.messages import voice_message 15 | from balebot.models.messages import template_response_message 16 | 17 | 18 | class MessageFactory: 19 | @staticmethod 20 | def create_message(json_dict): 21 | message_type = json_dict.get("$type") 22 | 23 | if message_type == MessageType.text_message: 24 | return text_message.TextMessage.load_from_json(json_dict) 25 | 26 | elif message_type == MessageType.template_message: 27 | return template_message.TemplateMessage.load_from_json(json_dict) 28 | 29 | elif message_type == MessageType.purchase_message: 30 | return purchase_message.PurchaseMessage.load_from_json(json_dict) 31 | 32 | elif message_type == MessageType.unsupported_message: 33 | return unsupported_message.UnsupportedMessage.load_from_json(json_dict) 34 | 35 | elif message_type == MessageType.sticker_message: 36 | return sticker_message.StickerMessage.load_from_json(json_dict) 37 | 38 | elif message_type == MessageType.json_message: 39 | 40 | if json_message.JsonMessage.is_raw_location_message(json_dict): 41 | return location_message.LocationMessage.load_from_json(json_dict) 42 | 43 | elif json_message.JsonMessage.is_raw_contact_message(json_dict): 44 | return contact_message.ContactMessage.load_from_json(json_dict) 45 | 46 | return json_message.JsonMessage.load_from_json(json_dict) 47 | 48 | elif message_type == MessageType.template_response_message: 49 | return template_response_message.TemplateResponseMessage.load_from_json(json_dict) 50 | 51 | elif message_type == MessageType.bank_message: 52 | return bank_message.BankMessage.load_from_json(json_dict) 53 | 54 | elif message_type == MessageType.document_message: 55 | 56 | if document_message.DocumentMessage.is_raw_document_message(json_dict): 57 | return document_message.DocumentMessage.load_from_json(json_dict) 58 | 59 | elif document_message.DocumentMessage.is_photo_message(json_dict): 60 | return photo_message.PhotoMessage.load_from_json(json_dict) 61 | 62 | elif document_message.DocumentMessage.is_video_message(json_dict): 63 | return video_message.VideoMessage.load_from_json(json_dict) 64 | 65 | elif document_message.DocumentMessage.is_voice_message(json_dict): 66 | return voice_message.VoiceMessage.load_from_json(json_dict) 67 | 68 | else: 69 | return None 70 | -------------------------------------------------------------------------------- /balebot/models/factories/raw_json_factory.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages import contact_message 2 | from balebot.models.messages import location_message 3 | from balebot.models.constants.raw_json_type import RawJsonType 4 | 5 | 6 | 7 | class RawJsonFactory: 8 | @staticmethod 9 | def create_raw_json(json_dict): 10 | json_type = json_dict.get("dataType", None) 11 | 12 | if json_type == RawJsonType.contact: 13 | return contact_message.ContactMessage.load_from_json(json_dict) 14 | 15 | elif json_type == RawJsonType.location: 16 | return location_message.LocationMessage.load_from_json(json_dict) 17 | 18 | else: 19 | return None 20 | -------------------------------------------------------------------------------- /balebot/models/factories/raw_value_factory.py: -------------------------------------------------------------------------------- 1 | from balebot.models.constants.value_type import ValueType 2 | from balebot.models.base_models.value_types import int32_val 3 | from balebot.models.base_models.value_types import int64_val 4 | from balebot.models.base_models.value_types import boolean_value 5 | from balebot.models.base_models.value_types import double_val 6 | from balebot.models.base_models.value_types import string_val 7 | from balebot.models.base_models.value_types import array_val 8 | from balebot.models.base_models.value_types import map_value 9 | 10 | 11 | class RawValueFactory: 12 | @staticmethod 13 | def create_raw_value(json_dict): 14 | raw_value_type = json_dict.get("$type", None) 15 | 16 | if raw_value_type == ValueType.int32_val: 17 | return int32_val.Int32Val.load_from_json(json_dict) 18 | 19 | if raw_value_type == ValueType.int64_val: 20 | return int64_val.Int64Val.load_from_json(json_dict) 21 | 22 | elif raw_value_type == ValueType.boolean_value: 23 | return boolean_value.BooleanValue.load_from_json(json_dict) 24 | 25 | elif raw_value_type == ValueType.double_val: 26 | return double_val.DoubleVal.load_from_json(json_dict) 27 | 28 | elif raw_value_type == ValueType.string_val: 29 | return string_val.StringVal.load_from_json(json_dict) 30 | 31 | elif raw_value_type == ValueType.array_val: 32 | return array_val.ArrayVal.load_from_json(json_dict) 33 | 34 | elif raw_value_type == ValueType.map_value: 35 | return map_value.MapValue.load_from_json(json_dict) 36 | 37 | @staticmethod 38 | def get_value(raw_value): 39 | if isinstance(raw_value, int32_val.Int32Val): 40 | return raw_value.value 41 | 42 | if isinstance(raw_value, int64_val.Int64Val): 43 | return raw_value.value 44 | 45 | elif isinstance(raw_value, boolean_value.BooleanValue): 46 | return raw_value.value 47 | 48 | elif isinstance(raw_value, double_val.DoubleVal): 49 | return raw_value.value 50 | 51 | elif isinstance(raw_value, string_val.StringVal): 52 | return raw_value.text 53 | 54 | elif isinstance(raw_value, array_val.ArrayVal): 55 | return raw_value.values 56 | 57 | elif isinstance(raw_value, map_value.MapValue): 58 | return raw_value.items 59 | -------------------------------------------------------------------------------- /balebot/models/factories/server_update_factory.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models import fat_seq_update 2 | 3 | from balebot.models.base_models import response 4 | 5 | 6 | class ServerUpdateFactory: 7 | @staticmethod 8 | def create_update(json_dict): 9 | update_type = json_dict.get("$type", None) 10 | 11 | if update_type == "Response": 12 | return response.Response(json_dict) 13 | 14 | elif update_type == "FatSeqUpdate": 15 | return fat_seq_update.FatSeqUpdate(json_dict) 16 | 17 | else: 18 | return 19 | -------------------------------------------------------------------------------- /balebot/models/factories/update_body_factory.py: -------------------------------------------------------------------------------- 1 | from balebot.models.constants.update_body_type import UpdateBodyType 2 | 3 | from balebot.models.server_updates import bot_read_update_body 4 | from balebot.models.server_updates import message_update_body 5 | from balebot.models.server_updates import raw_update_body 6 | from balebot.models.server_updates import bot_received_update_body 7 | 8 | 9 | class UpdateBodyFactory: 10 | @staticmethod 11 | def create_update_body(body_json_dict): 12 | update_body_type = body_json_dict.get("$type", None) 13 | 14 | if update_body_type == UpdateBodyType.message: 15 | return message_update_body.MessageUpdate(body_json_dict) 16 | 17 | elif update_body_type == UpdateBodyType.bot_read_update: 18 | return bot_read_update_body.BotReadUpdate(body_json_dict) 19 | 20 | elif update_body_type == UpdateBodyType.bot_received_update: 21 | return bot_received_update_body.BotReceivedUpdate(body_json_dict) 22 | 23 | elif update_body_type == UpdateBodyType.raw_update: 24 | return raw_update_body.RawUpdate(body_json_dict) 25 | -------------------------------------------------------------------------------- /balebot/models/messages/__init__.py: -------------------------------------------------------------------------------- 1 | from balebot.models.messages.banking.purchase_message import PurchaseMessage 2 | from balebot.models.messages.banking.bank_message import BankMessage 3 | 4 | from balebot.models.messages.template.template_message import TemplateMessage 5 | from balebot.models.messages.template.template_message_button import TemplateMessageButton 6 | 7 | from balebot.models.messages.template_response_message import TemplateResponseMessage 8 | from balebot.models.messages.base_message import BaseMessage 9 | from balebot.models.messages.json_message import JsonMessage 10 | from balebot.models.messages.location_message import LocationMessage 11 | from balebot.models.messages.contact_message import ContactMessage 12 | from balebot.models.messages.text_message import TextMessage 13 | from balebot.models.messages.unsupported_message import UnsupportedMessage 14 | from balebot.models.messages.photo_message import PhotoMessage 15 | from balebot.models.messages.document_message import DocumentMessage 16 | from balebot.models.messages.sticker_message import StickerMessage 17 | from balebot.models.messages.video_message import VideoMessage 18 | from balebot.models.messages.voice_message import VoiceMessage 19 | -------------------------------------------------------------------------------- /balebot/models/messages/banking/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/messages/banking/__init__.py -------------------------------------------------------------------------------- /balebot/models/messages/banking/bank_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.banking.bank_ext import BankExt 4 | from balebot.models.constants.errors import Error 5 | from balebot.models.constants.message_type import MessageType 6 | from balebot.models.factories import bank_ext_factory 7 | from balebot.models.messages.base_message import BaseMessage 8 | 9 | 10 | class BankMessage(BaseMessage): 11 | def __init__(self, bank_ext_message): 12 | 13 | if isinstance(bank_ext_message, BankExt): 14 | self.bank_ext_message = bank_ext_message 15 | else: 16 | raise ValueError(Error.unacceptable_object_type) 17 | 18 | def get_receipt(self): 19 | from balebot.models.base_models.banking.receipt_message import ReceiptMessage 20 | if isinstance(self.bank_ext_message, ReceiptMessage): 21 | return self.bank_ext_message.generate_receipt_from_transfer_info_items() 22 | 23 | def get_json_object(self): 24 | 25 | data = { 26 | "$type": MessageType.bank_message, 27 | "message": self.bank_ext_message.get_json_object(), 28 | } 29 | return data 30 | 31 | def get_json_str(self): 32 | return json_handler.dumps(self.get_json_object()) 33 | 34 | @classmethod 35 | def load_from_json(cls, json): 36 | if isinstance(json, dict): 37 | json_dict = json 38 | elif isinstance(json, str): 39 | json_dict = json_handler.loads(json) 40 | else: 41 | raise ValueError(Error.unacceptable_json) 42 | 43 | bank_ext_message = bank_ext_factory.BankExtFactory.create_bank_ext(json_dict.get('message', None)) 44 | 45 | if bank_ext_message is None: 46 | raise ValueError(Error.none_or_invalid_attribute) 47 | 48 | return cls(bank_ext_message=bank_ext_message) 49 | -------------------------------------------------------------------------------- /balebot/models/messages/banking/money_request_type.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class MoneyRequestType(Enum): 5 | normal = "MoneyRequestNormal" 6 | bill = "MoneyRequestBill" 7 | payment = "MoneyRequestPayment" 8 | 9 | def __str__(self): 10 | return self.value 11 | 12 | -------------------------------------------------------------------------------- /balebot/models/messages/base_message.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models.jsonable import Jsonable 2 | 3 | 4 | class BaseMessage(Jsonable): 5 | pass 6 | -------------------------------------------------------------------------------- /balebot/models/messages/contact_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.raw_json import RawJson 4 | from balebot.models.messages.base_message import BaseMessage 5 | from balebot.models.constants.errors import Error 6 | from balebot.models.constants.raw_json_type import RawJsonType 7 | from balebot.models.constants.message_type import MessageType 8 | 9 | 10 | class ContactMessage(RawJson, BaseMessage): 11 | def __init__(self, name, emails, phones): 12 | self.name = str(name) 13 | 14 | if isinstance(emails, list): 15 | self.emails = [str(email) for email in emails] 16 | else: 17 | raise ValueError(Error.unacceptable_object_type) 18 | 19 | if isinstance(phones, list): 20 | self.phones = ["".join(str(phone).split(" ")) for phone in phones] 21 | else: 22 | raise ValueError(Error.unacceptable_object_type) 23 | 24 | def get_json_object(self): 25 | 26 | data = { 27 | "$type": MessageType.json_message, 28 | "rawJson": json_handler.dumps({ 29 | "dataType": RawJsonType.contact, 30 | "data": { 31 | RawJsonType.contact: { 32 | "name": self.name, 33 | "emails": self.emails, 34 | "phones": self.phones 35 | } 36 | } 37 | }) 38 | } 39 | return data 40 | 41 | def get_json_str(self): 42 | return json_handler.dumps(self.get_json_object()) 43 | 44 | @classmethod 45 | def load_from_json(cls, json): 46 | if isinstance(json, dict): 47 | json_dict = json 48 | elif isinstance(json, str): 49 | json_dict = json_handler.loads(json) 50 | else: 51 | raise ValueError(Error.unacceptable_json) 52 | 53 | json_dict = json_handler.loads(json_dict.get('rawJson')) 54 | data = json_dict.get('data', None) 55 | contact = data.get(RawJsonType.contact, None) 56 | name = contact.get('name', None) 57 | emails = contact.get('emails', None) 58 | phones = contact.get('phones', None) 59 | 60 | return cls(name=name, emails=emails, phones=phones) 61 | -------------------------------------------------------------------------------- /balebot/models/messages/document_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.constants.document_type import DocumentType 4 | from balebot.models.constants.message_type import MessageType 5 | from balebot.models.messages.base_message import BaseMessage 6 | from balebot.models.constants.errors import Error 7 | 8 | from balebot.models.messages.text_message import TextMessage 9 | 10 | 11 | class DocumentMessage(BaseMessage): 12 | def __init__(self, file_id, access_hash, name, file_size, mime_type, caption_text=None, 13 | checksum=None, algorithm=None, file_storage_version=1): 14 | self.file_id = str(file_id) 15 | self.access_hash = str(access_hash) 16 | self.file_size = str(file_size) 17 | self.name = str(name) 18 | self.mime_type = str(mime_type) 19 | 20 | if caption_text: 21 | if isinstance(caption_text, TextMessage): 22 | self.caption_text = caption_text 23 | else: 24 | self.caption_text = None 25 | 26 | self.checksum = str(checksum) if checksum else "checkSum" 27 | self.algorithm = str(algorithm) if algorithm else "algorithm" 28 | self.file_storage_version = int(file_storage_version) 29 | 30 | def get_json_object(self): 31 | data = { 32 | "$type": MessageType.document_message, 33 | "fileId": self.file_id, 34 | "accessHash": self.access_hash, 35 | "fileSize": self.file_size, 36 | "name": self.name, 37 | "mimeType": self.mime_type, 38 | "thumb": None, 39 | "ext": None, 40 | "caption": self.caption_text.get_json_object() if self.caption_text else None, 41 | "checkSum": self.checksum, 42 | "algorithm": self.algorithm, 43 | "fileStorageVersion": self.file_storage_version 44 | 45 | } 46 | return data 47 | 48 | def get_json_str(self): 49 | return json_handler.dumps(self.get_json_object()) 50 | 51 | @classmethod 52 | def load_from_json(cls, json): 53 | if isinstance(json, dict): 54 | json_dict = json 55 | elif isinstance(json, str): 56 | json_dict = json_handler.loads(json) 57 | else: 58 | raise ValueError(Error.unacceptable_json) 59 | 60 | file_id = json_dict.get('fileId', None) 61 | access_hash = json_dict.get('accessHash', None) 62 | file_size = json_dict.get('fileSize', None) 63 | name = json_dict.get('name', None) 64 | mime_type = json_dict.get('mimeType', None) 65 | 66 | caption_message = TextMessage.load_from_json(json_dict.get('caption', None)) 67 | 68 | checksum = json_dict.get('checkSum', None) 69 | algorithm = json_dict.get('algorithm', None) 70 | file_storage_version = json_dict.get('fileStorageVersion', None) 71 | 72 | if (not file_id) or (not access_hash) or (name is None) or (file_size is None) or (mime_type is None): 73 | raise ValueError(Error.none_or_invalid_attribute) 74 | 75 | return cls(file_id=file_id, access_hash=access_hash, name=name, file_size=file_size, 76 | mime_type=mime_type, file_storage_version=file_storage_version, caption_text=caption_message, 77 | checksum=checksum, algorithm=algorithm) 78 | 79 | @staticmethod 80 | def is_video_message(json_dict): 81 | message_type = json_dict.get("$type", None) 82 | message_ext = json_dict.get("ext", None) 83 | document_type = message_ext.get("$type", None) 84 | 85 | return message_type == MessageType.document_message and document_type == DocumentType.video_document 86 | 87 | @staticmethod 88 | def is_photo_message(json_dict): 89 | message_type = json_dict.get("$type", None) 90 | message_ext = json_dict.get("ext", None) 91 | document_type = message_ext.get("$type", None) 92 | 93 | return message_type == MessageType.document_message and document_type == DocumentType.photo_document 94 | 95 | @staticmethod 96 | def is_voice_message(json_dict): 97 | message_type = json_dict.get("$type", None) 98 | message_ext = json_dict.get("ext", None) 99 | document_type = message_ext.get("$type", None) 100 | 101 | return message_type == MessageType.document_message and document_type == DocumentType.voice_document 102 | 103 | @staticmethod 104 | def is_raw_document_message(json_dict): 105 | message_type = json_dict.get("$type", None) 106 | message_ext = json_dict.get("ext", None) 107 | 108 | return message_type == MessageType.document_message and not message_ext 109 | -------------------------------------------------------------------------------- /balebot/models/messages/json_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.raw_json import RawJson 4 | from balebot.models.messages.base_message import BaseMessage 5 | from balebot.models.constants.errors import Error 6 | from balebot.models.factories import raw_json_factory 7 | from balebot.models.constants.message_type import MessageType 8 | 9 | 10 | class JsonMessage(BaseMessage): 11 | def __init__(self, raw_json): 12 | if isinstance(raw_json, RawJson): 13 | self.raw_json = raw_json 14 | 15 | def get_json_object(self): 16 | 17 | data = { 18 | "$type": MessageType.json_message, 19 | "rawJson": self.raw_json.get_json_str() 20 | 21 | } 22 | return data 23 | 24 | def get_json_str(self): 25 | return json_handler.dumps(self.get_json_object()) 26 | 27 | @classmethod 28 | def load_from_json(cls, json): 29 | if isinstance(json, dict): 30 | json_dict = json 31 | elif isinstance(json, str): 32 | json_dict = json_handler.loads(json) 33 | else: 34 | raise ValueError(Error.unacceptable_json) 35 | 36 | raw_json_dict = json_handler.loads(json_dict.get('rawJson', None)) 37 | raw_json = raw_json_factory.RawJsonFactory.create_raw_json(raw_json_dict) 38 | 39 | if raw_json is None: 40 | raise ValueError(Error.none_or_invalid_attribute) 41 | 42 | return cls(raw_json=raw_json) 43 | 44 | @staticmethod 45 | def is_raw_location_message(json): 46 | json_dict = json_handler.loads(json.get('rawJson')) 47 | raw_json_type = json_dict.get('dataType') if json_dict else None 48 | 49 | return raw_json_type == MessageType.location_message 50 | 51 | @staticmethod 52 | def is_raw_contact_message(json): 53 | json_dict = json_handler.loads(json.get('rawJson')) 54 | raw_json_type = json_dict.get('dataType') if json_dict else None 55 | 56 | return raw_json_type == MessageType.contact_message 57 | -------------------------------------------------------------------------------- /balebot/models/messages/location_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.constants.raw_json_type import RawJsonType 4 | from balebot.models.base_models.raw_json import RawJson 5 | from balebot.models.messages.base_message import BaseMessage 6 | from balebot.models.constants.errors import Error 7 | from balebot.models.constants.message_type import MessageType 8 | 9 | 10 | class LocationMessage(RawJson, BaseMessage): 11 | def __init__(self, latitude, longitude): 12 | self.latitude = float(latitude) 13 | self.longitude = float(longitude) 14 | 15 | def get_json_object(self): 16 | 17 | data = { 18 | "$type": MessageType.json_message, 19 | "rawJson": json_handler.dumps({ 20 | "dataType": RawJsonType.location, 21 | "data": { 22 | RawJsonType.location: { 23 | "latitude": self.latitude, 24 | "longitude": self.longitude 25 | } 26 | } 27 | }) 28 | } 29 | return data 30 | 31 | def get_json_str(self): 32 | return json_handler.dumps(self.get_json_object()) 33 | 34 | @classmethod 35 | def load_from_json(cls, json): 36 | if isinstance(json, dict): 37 | json_dict = json 38 | elif isinstance(json, str): 39 | json_dict = json_handler.loads(json) 40 | else: 41 | raise ValueError(Error.unacceptable_json) 42 | 43 | json_dict = json_handler.loads(json_dict.get('rawJson')) 44 | data = json_dict.get('data', None) 45 | location = data.get(RawJsonType.location, None) 46 | latitude = location.get('latitude', None) 47 | longitude = location.get('longitude', None) 48 | 49 | return cls(latitude=latitude, longitude=longitude) 50 | -------------------------------------------------------------------------------- /balebot/models/messages/photo_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.messages.document_message import DocumentMessage 4 | 5 | from balebot.models.constants.document_type import DocumentType 6 | from balebot.models.messages.text_message import TextMessage 7 | 8 | 9 | class PhotoMessage(DocumentMessage): 10 | def __init__(self, file_id, access_hash, name, file_size, mime_type, thumb, width=80, height=80, ext_width=None, 11 | ext_height=None, file_storage_version=None, caption_text=None, checksum=None, algorithm=None): 12 | 13 | super(PhotoMessage, self).__init__(file_id, access_hash, name, file_size, mime_type, 14 | caption_text, checksum, algorithm, file_storage_version) 15 | self.thumb = str(thumb) 16 | self.width = int(width) 17 | self.height = int(height) 18 | self.ext_width = int(ext_width) if ext_width else width 19 | self.ext_height = int(ext_height) if ext_height else height 20 | 21 | def get_json_object(self): 22 | 23 | data = super().get_json_object() 24 | data["thumb"] = { 25 | "width": self.width, 26 | "height": self.height, 27 | "thumb": self.thumb 28 | } 29 | data["ext"] = { 30 | "$type": DocumentType.photo_document, 31 | "width": self.ext_width, 32 | "height": self.ext_height, 33 | } 34 | 35 | return data 36 | 37 | def get_json_str(self): 38 | return json_handler.dumps(self.get_json_object()) 39 | 40 | @classmethod 41 | def load_from_json(cls, json): 42 | if isinstance(json, dict): 43 | json_dict = json 44 | elif isinstance(json, str): 45 | json_dict = json_handler.loads(json) 46 | else: 47 | raise ValueError("json input has unacceptable format.") 48 | 49 | file_id = json_dict.get('fileId', None) 50 | access_hash = json_dict.get('accessHash', None) 51 | name = json_dict.get('name', None) 52 | file_size = json_dict.get('fileSize', None) 53 | mime_type = json_dict.get('mimeType', None) 54 | 55 | ext = json_dict.get('ext', None) 56 | ext_width = ext.get('width', None) 57 | ext_height = ext.get('height', None) 58 | 59 | thumb = json_dict.get('thumb', None) 60 | width = thumb.get('width', None) 61 | height = thumb.get('height', None) 62 | thumb_txt = thumb.get('thumb', None) 63 | 64 | file_storage_version = json_dict.get('fileStorageVersion', None) 65 | 66 | caption_message = TextMessage.load_from_json(json_dict.get('caption', None)) 67 | 68 | checksum = json_dict.get('checkSum', None) 69 | algorithm = json_dict.get('algorithm', None) 70 | 71 | if (not file_id) or (not access_hash) or (name is None) or (file_size is None) or \ 72 | (mime_type is None) or (width is None) or (height is None) or \ 73 | (ext_width is None) or (ext_height is None) or (thumb_txt is None): 74 | raise ValueError("main parameters should have value.") 75 | 76 | return cls(file_id=file_id, access_hash=access_hash, name=name, file_size=file_size, 77 | mime_type=mime_type, width=width, height=height, ext_width=ext_width, ext_height=ext_height, 78 | thumb=thumb_txt, file_storage_version=file_storage_version, caption_text=caption_message, 79 | checksum=checksum, algorithm=algorithm) 80 | -------------------------------------------------------------------------------- /balebot/models/messages/sticker_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.image_location import ImageLocation 4 | from balebot.models.messages.base_message import BaseMessage 5 | from balebot.models.constants.errors import Error 6 | 7 | from balebot.models.constants.message_type import MessageType 8 | 9 | 10 | class StickerMessage(BaseMessage): 11 | def __init__(self, sticker_id=None, sticker_collection_id=None, sticker_collection_access_hash=None, 12 | fast_preview=None, image512=None, image256=None): 13 | self._sticker_id = str(sticker_id) if sticker_id else None 14 | self._sticker_collection_id = str(sticker_collection_id) if sticker_collection_id else None 15 | self._sticker_collection_access_hash = str( 16 | sticker_collection_access_hash) if sticker_collection_access_hash else None 17 | self._fast_preview = list(fast_preview) if fast_preview else None 18 | 19 | if image512: 20 | if isinstance(image512, ImageLocation): 21 | self._image512 = image512 22 | else: 23 | raise ValueError(Error.unacceptable_object_type) 24 | else: 25 | self._image512 = None 26 | 27 | if image256: 28 | if isinstance(image256, ImageLocation): 29 | self._image256 = image256 30 | else: 31 | raise ValueError(Error.unacceptable_object_type) 32 | else: 33 | self._image256 = None 34 | 35 | def get_json_object(self): 36 | 37 | data = { 38 | "$type": MessageType.sticker_message, 39 | "stickerId": self._sticker_id, 40 | "stickerCollectionId": self._sticker_collection_id, 41 | "stickerCollectionAccessHash": self._sticker_collection_access_hash, 42 | "fastPreview": self._fast_preview, 43 | "image512": self._image512.get_json_object() if self._image512 else None, 44 | "image256": self._image256.get_json_object() if self._image256 else None, 45 | 46 | } 47 | return data 48 | 49 | def get_json_str(self): 50 | return json_handler.dumps(self.get_json_object()) 51 | 52 | @classmethod 53 | def load_from_json(cls, json): 54 | if isinstance(json, dict): 55 | json_dict = json 56 | elif isinstance(json, str): 57 | json_dict = json_handler.loads(json) 58 | else: 59 | raise ValueError(Error.unacceptable_json) 60 | 61 | sticker_id = json_dict.get("stickerId", None) 62 | sticker_collection_id = json_dict.get("stickerCollectionId", None) 63 | sticker_collection_access_hash = json_dict.get("stickerCollectionAccessHash", None) 64 | fast_preview = json_dict.get("fastPreview ", None) 65 | image512 = ImageLocation.load_from_json(json_dict.get("image512", None)) if json_dict.get("image512", 66 | None) else None 67 | image256 = ImageLocation.load_from_json(json_dict.get("image256", None)) if json_dict.get("image256", 68 | None) else None 69 | 70 | return cls(sticker_id=sticker_id, sticker_collection_id=sticker_collection_id, 71 | sticker_collection_access_hash=sticker_collection_access_hash, fast_preview=fast_preview, 72 | image512=image512, image256=image256) 73 | -------------------------------------------------------------------------------- /balebot/models/messages/template/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/messages/template/__init__.py -------------------------------------------------------------------------------- /balebot/models/messages/template/template_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.constants.message_type import MessageType 4 | from balebot.models.messages.base_message import BaseMessage 5 | from balebot.models.constants.errors import Error 6 | 7 | from balebot.models.messages.template.template_message_button import TemplateMessageButton 8 | 9 | 10 | class TemplateMessage(BaseMessage): 11 | message_id_counter = 0 12 | 13 | def __init__(self, general_message, btn_list): 14 | 15 | if isinstance(general_message, BaseMessage): 16 | self.general_message = general_message 17 | else: 18 | raise ValueError(Error.unacceptable_object_type) 19 | 20 | if isinstance(btn_list, list) and all(isinstance(btn, TemplateMessageButton) for btn in btn_list): 21 | self.btn_list = btn_list 22 | elif btn_list is None: 23 | self.btn_list = [] 24 | else: 25 | raise ValueError(Error.unacceptable_object_type) 26 | 27 | self.template_message_id = str(TemplateMessage.message_id_counter) 28 | TemplateMessage.message_id_counter += 1 29 | 30 | def get_json_object(self): 31 | data = { 32 | "$type": MessageType.template_message, 33 | "generalMessage": self.general_message.get_json_object(), 34 | "templateMessageId": self.template_message_id, 35 | "btnList": [btn.get_json_object() for btn in self.btn_list], 36 | 37 | } 38 | return data 39 | 40 | def get_json_str(self): 41 | return json_handler.dumps(self.get_json_object()) 42 | 43 | def add_button(self, btn): 44 | if isinstance(btn, TemplateMessageButton): 45 | self.btn_list.append(btn) 46 | else: 47 | raise ValueError(Error.unacceptable_object_type) 48 | 49 | @classmethod 50 | def load_from_json(cls, json): 51 | if isinstance(json, dict): 52 | json_dict = json 53 | elif isinstance(json, str): 54 | json_dict = json_handler.loads(json) 55 | else: 56 | raise ValueError(Error.unacceptable_json) 57 | 58 | from balebot.models.factories import message_factory 59 | general_message = message_factory.MessageFactory.create_message(json_dict.get("generalMessage")) 60 | bt_list = json_dict.get('btnList') 61 | btn_list = [TemplateMessageButton(btn['text'], btn['value'], 0) for btn in bt_list] 62 | if general_message is None or bt_list is None: 63 | raise ValueError(Error.none_or_invalid_attribute) 64 | 65 | return cls(general_message=general_message, btn_list=btn_list) 66 | -------------------------------------------------------------------------------- /balebot/models/messages/template/template_message_button.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | 4 | class TemplateMessageButton: 5 | # text: str 6 | # value: str 7 | # action: int 8 | 9 | def __init__(self, text, value=None, action=None): 10 | self.text = str(text) 11 | self.value = str(value or text) 12 | self.action = int(action or 0) 13 | 14 | def get_json_object(self): 15 | data = { 16 | "text": self.text, 17 | "value": self.value, 18 | "action": self.action, 19 | } 20 | return data 21 | 22 | def get_json_str(self): 23 | return json_handler.dumps(self.get_json_object()) 24 | 25 | @classmethod 26 | def load_from_json(cls, json): 27 | pass 28 | -------------------------------------------------------------------------------- /balebot/models/messages/template_response_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.messages.base_message import BaseMessage 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.message_type import MessageType 7 | 8 | 9 | class TemplateResponseMessage(BaseMessage): 10 | def __init__(self, text, template_message_response_id): 11 | self.text = str(text) 12 | self.text_message = self.text 13 | self.template_message_response_id = str(template_message_response_id) 14 | 15 | def get_json_object(self): 16 | data = { 17 | "$type": MessageType.template_response_message, 18 | "textMessage": self.text, 19 | "templateMessageResponseId": self.template_message_response_id, 20 | } 21 | return data 22 | 23 | def get_json_str(self): 24 | return json_handler.dumps(self.get_json_object()) 25 | 26 | @classmethod 27 | def load_from_json(cls, json): 28 | if isinstance(json, dict): 29 | json_dict = json 30 | elif isinstance(json, str): 31 | json_dict = json_handler.loads(json) 32 | else: 33 | raise ValueError(Error.unacceptable_json) 34 | 35 | text_message = json_dict.get("textMessage", None) 36 | template_message_response_id = json_dict.get("templateMessageResponseId", None) 37 | 38 | if (text_message is None) or (template_message_response_id is None): 39 | raise ValueError(Error.none_or_invalid_attribute) 40 | 41 | return cls(text=text_message, template_message_response_id=template_message_response_id) 42 | -------------------------------------------------------------------------------- /balebot/models/messages/text_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.messages.base_message import BaseMessage 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.message_type import MessageType 7 | 8 | 9 | class TextMessage(BaseMessage): 10 | def __init__(self, text): 11 | 12 | self.text = str(text) if text else "" 13 | 14 | def get_json_object(self): 15 | data = { 16 | "$type": MessageType.text_message, 17 | "text": self.text 18 | 19 | } 20 | return data 21 | 22 | def get_json_str(self): 23 | return json_handler.dumps(self.get_json_object()) 24 | 25 | @classmethod 26 | def load_from_json(cls, json): 27 | if isinstance(json, dict): 28 | json_dict = json 29 | elif isinstance(json, str): 30 | json_dict = json_handler.loads(json) 31 | else: 32 | raise ValueError(Error.unacceptable_json) 33 | 34 | text = json_dict.get('text', None) 35 | if text is None: 36 | raise ValueError(Error.none_or_invalid_attribute) 37 | 38 | return cls(text=text) 39 | -------------------------------------------------------------------------------- /balebot/models/messages/unsupported_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.messages.base_message import BaseMessage 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.message_type import MessageType 7 | 8 | 9 | class UnsupportedMessage(BaseMessage): 10 | def get_json_object(self): 11 | data = { 12 | "$type": MessageType.unsupported_message, 13 | } 14 | return data 15 | 16 | def get_json_str(self): 17 | return json_handler.dumps(self.get_json_object()) 18 | 19 | @classmethod 20 | def load_from_json(cls, json): 21 | if isinstance(json, dict): 22 | json_dict = json 23 | elif isinstance(json, str): 24 | json_dict = json_handler.loads(json) 25 | else: 26 | raise ValueError(Error.unacceptable_json) 27 | 28 | return cls() 29 | -------------------------------------------------------------------------------- /balebot/models/messages/video_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.messages.document_message import DocumentMessage 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.document_type import DocumentType 7 | from balebot.models.messages.text_message import TextMessage 8 | 9 | 10 | class VideoMessage(DocumentMessage): 11 | def __init__(self, file_id, access_hash, name, file_size, mime_type, thumb, duration, width=80, height=80, 12 | ext_width=None, ext_height=None, file_storage_version=None, caption_text=None, checksum=None, 13 | algorithm=None): 14 | 15 | super(VideoMessage, self).__init__(file_id, access_hash, name, file_size, mime_type, 16 | caption_text, checksum, algorithm, file_storage_version) 17 | 18 | self.thumb = str(thumb) 19 | self.duration = int(duration) 20 | self.width = int(width) 21 | self.height = int(height) 22 | self.ext_width = int(ext_width) if ext_width else width 23 | self.ext_height = int(ext_height) if ext_height else height 24 | 25 | def get_json_object(self): 26 | 27 | data = super().get_json_object() 28 | data["thumb"] = { 29 | "width": self.width, 30 | "height": self.height, 31 | "thumb": self.thumb 32 | } 33 | data["ext"] = { 34 | "$type": DocumentType.video_document, 35 | "width": self.ext_width, 36 | "height": self.ext_height, 37 | "duration": self.duration 38 | } 39 | 40 | return data 41 | 42 | def get_json_str(self): 43 | return json_handler.dumps(self.get_json_object()) 44 | 45 | @classmethod 46 | def load_from_json(cls, json): 47 | if isinstance(json, dict): 48 | json_dict = json 49 | elif isinstance(json, str): 50 | json_dict = json_handler.loads(json) 51 | else: 52 | raise ValueError(Error.unacceptable_json) 53 | 54 | file_id = json_dict.get('fileId', None) 55 | access_hash = json_dict.get('accessHash', None) 56 | name = json_dict.get('name', None) 57 | file_size = json_dict.get('fileSize', None) 58 | mime_type = json_dict.get('mimeType', None) 59 | 60 | ext = json_dict.get('ext', None) 61 | ext_width = ext.get('width', None) 62 | ext_height = ext.get('height', None) 63 | duration = ext.get('duration', None) 64 | 65 | thumb = json_dict.get('thumb', None) 66 | width = thumb.get('width', None) 67 | height = thumb.get('height', None) 68 | thumb_txt = thumb.get('thumb', None) 69 | 70 | file_storage_version = json_dict.get('fileStorageVersion', None) 71 | 72 | caption_message = TextMessage.load_from_json(json_dict.get('caption', None)) 73 | 74 | checksum = json_dict.get('checkSum', None) 75 | algorithm = json_dict.get('algorithm', None) 76 | 77 | if (not file_id) or (not access_hash) or (name is None) or (file_size is None) \ 78 | or (mime_type is None) or (width is None) or (height is None) or (ext_width is None) \ 79 | or (ext_height is None) or (thumb_txt is None) or (duration is None): 80 | raise ValueError(Error.none_or_invalid_attribute) 81 | 82 | return cls(file_id=file_id, access_hash=access_hash, name=name, file_size=file_size, 83 | mime_type=mime_type, thumb=thumb_txt, duration=duration, width=width, height=height, 84 | file_storage_version=file_storage_version, caption_text=caption_message, checksum=checksum, 85 | algorithm=algorithm) 86 | -------------------------------------------------------------------------------- /balebot/models/messages/voice_message.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.messages.document_message import DocumentMessage 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.constants.document_type import DocumentType 7 | from balebot.models.messages.text_message import TextMessage 8 | 9 | 10 | class VoiceMessage(DocumentMessage): 11 | def __init__(self, file_id, access_hash, name, file_size, mime_type, duration, file_storage_version=None, 12 | caption_text=None, checksum=None, algorithm=None): 13 | 14 | super(VoiceMessage, self).__init__(file_id, access_hash, name, file_size, mime_type, 15 | caption_text, checksum, algorithm, file_storage_version) 16 | self.duration = int(duration) 17 | 18 | def get_json_object(self): 19 | 20 | data = super().get_json_object() 21 | data["ext"] = { 22 | "$type": DocumentType.voice_document, 23 | "duration": self.duration 24 | } 25 | 26 | return data 27 | 28 | def get_json_str(self): 29 | return json_handler.dumps(self.get_json_object()) 30 | 31 | @classmethod 32 | def load_from_json(cls, json): 33 | if isinstance(json, dict): 34 | json_dict = json 35 | elif isinstance(json, str): 36 | json_dict = json_handler.loads(json) 37 | else: 38 | raise ValueError(Error.unacceptable_json) 39 | 40 | file_id = json_dict.get('fileId', None) 41 | access_hash = json_dict.get('accessHash', None) 42 | name = json_dict.get('name', None) 43 | file_size = json_dict.get('fileSize', None) 44 | mime_type = json_dict.get('mimeType', None) 45 | 46 | ext = json_dict.get('ext', None) 47 | duration = ext.get('duration', None) 48 | 49 | file_storage_version = json_dict.get('fileStorageVersion', None) 50 | 51 | caption_message = TextMessage.load_from_json(json_dict.get('caption', None)) 52 | 53 | checksum = json_dict.get('checkSum', None) 54 | algorithm = json_dict.get('algorithm', None) 55 | 56 | if (not file_id) or (not access_hash) or (not name) or (file_size is None) or (not mime_type) or ( 57 | duration is None): 58 | raise ValueError(Error.none_or_invalid_attribute) 59 | 60 | return cls(file_id=file_id, access_hash=access_hash, name=name, file_size=file_size, 61 | mime_type=mime_type, duration=duration, file_storage_version=file_storage_version, 62 | caption_text=caption_message, checksum=checksum, algorithm=algorithm) 63 | -------------------------------------------------------------------------------- /balebot/models/server_responses/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/server_responses/__init__.py -------------------------------------------------------------------------------- /balebot/models/server_responses/bot_error_response.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.response_body import ResponseBody 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class BotError(ResponseBody): 8 | def __init__(self, json): 9 | if isinstance(json, dict): 10 | json_dict = json 11 | elif isinstance(json, str): 12 | json_dict = json_handler.loads(json) 13 | else: 14 | raise ValueError(Error.unacceptable_json) 15 | 16 | self.code = json_dict.get("code", None) 17 | self.tag = json_dict.get("tag", None) 18 | self.data = json_dict.get("data", None) 19 | self.retry_in = json_dict.get("retryIn", None) 20 | -------------------------------------------------------------------------------- /balebot/models/server_responses/bot_success_response.py: -------------------------------------------------------------------------------- 1 | from balebot.models.base_models.response_body import ResponseBody 2 | 3 | 4 | class BotSuccess(ResponseBody): 5 | pass 6 | -------------------------------------------------------------------------------- /balebot/models/server_responses/files/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/server_responses/files/__init__.py -------------------------------------------------------------------------------- /balebot/models/server_responses/files/response_get_download_url.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.request_body import RequestBody 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class ResponseGetDownloadUrl(RequestBody): 8 | def __init__(self, json): 9 | if isinstance(json, dict): 10 | json_dict = json 11 | elif isinstance(json, str): 12 | json_dict = json_handler.loads(json) 13 | else: 14 | raise ValueError(Error.unacceptable_json) 15 | 16 | self.url = json_dict.get("url", None) 17 | -------------------------------------------------------------------------------- /balebot/models/server_responses/files/response_get_upload_url.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.request_body import RequestBody 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class ResponseGetUploadUrl(RequestBody): 8 | def __init__(self, json): 9 | if isinstance(json, dict): 10 | json_dict = json 11 | elif isinstance(json, str): 12 | json_dict = json_handler.loads(json) 13 | else: 14 | raise ValueError(Error.unacceptable_json) 15 | 16 | self.file_id = json_dict.get("fileId", None) 17 | self.user_id = json_dict.get("userId", None) 18 | self.url = json_dict.get("url", None) 19 | self.dup = json_dict.get("dup", None) 20 | -------------------------------------------------------------------------------- /balebot/models/server_responses/group/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/server_responses/group/__init__.py -------------------------------------------------------------------------------- /balebot/models/server_responses/group/get_group_api_response.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.avatar import Avatar 4 | from balebot.models.base_models.response_body import ResponseBody 5 | from balebot.models.base_models.value_types.map_value import MapValue 6 | from balebot.models.constants.errors import Error 7 | 8 | from balebot.models.base_models.member import Member 9 | 10 | 11 | class GetGroupApiResponse(ResponseBody): 12 | def __init__(self, json): 13 | if isinstance(json, dict): 14 | json_dict = json 15 | elif isinstance(json, str): 16 | json_dict = json_handler.loads(json) 17 | else: 18 | raise ValueError(Error.unacceptable_json) 19 | 20 | self.id = json_dict.get("id", None) 21 | self.access_hash = json_dict.get("accessHash", None) 22 | self.title = json_dict.get("title", None) 23 | 24 | self.avatar = Avatar.load_from_json(json_dict.get("avatar", None)) if json_dict.get("avatar", None) else None 25 | 26 | self.is_member = json_dict.get("isMember", None) 27 | self.creator_user_id = json_dict.get("creatorUserId", None) 28 | 29 | self.members = [Member.load_from_json(member) for member in json_dict.get("members", None)] if json_dict.get( 30 | "members", None) else None 31 | 32 | self.create_date = json_dict.get("createDate", None) 33 | self.is_admin = json_dict.get("isAdmin", None) 34 | self.theme = json_dict.get("theme", None) 35 | self.about = json_dict.get("about", None) 36 | self.is_hidden = json_dict.get("isHidden", None) 37 | self.ext = MapValue.load_from_json(json_dict.get("ext", None)) if json_dict.get("ext", None) else None 38 | self.members_count = json_dict.get("membersCount", None) 39 | self.group_type = json_dict.get("groupType", None)["$type"] 40 | self.can_send_message = json_dict.get("canSendMessage", None) 41 | self.nick = json_dict.get("nick", None) 42 | self.became_orphaned = json_dict.get("becameOrphaned", None) 43 | self.state_version = json_dict.get("stateVersion", None) 44 | -------------------------------------------------------------------------------- /balebot/models/server_responses/group/response_create_group.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.group_peer import GroupPeer 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.base_models.response_body import ResponseBody 7 | 8 | 9 | class ResponseCreateGroup(ResponseBody): 10 | def __init__(self, json): 11 | if isinstance(json, dict): 12 | json_dict = json 13 | elif isinstance(json, str): 14 | json_dict = json_handler.loads(json) 15 | else: 16 | raise ValueError(Error.unacceptable_json) 17 | 18 | self.group_peer = GroupPeer.load_from_json(json_dict.get("peer", None)) 19 | -------------------------------------------------------------------------------- /balebot/models/server_responses/messaging/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/server_responses/messaging/__init__.py -------------------------------------------------------------------------------- /balebot/models/server_responses/messaging/message_edited.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.response_body import ResponseBody 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class MessageEdited(ResponseBody): 8 | def __init__(self, json): 9 | if isinstance(json, dict): 10 | json_dict = json 11 | elif isinstance(json, str): 12 | json_dict = json_handler.loads(json) 13 | else: 14 | raise ValueError(Error.unacceptable_json) 15 | 16 | self.date = json_dict.get("date", None) 17 | self.seq = json_dict.get("seq", None) 18 | -------------------------------------------------------------------------------- /balebot/models/server_responses/messaging/message_sent.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.response_body import ResponseBody 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class MessageSent(ResponseBody): 8 | def __init__(self, json): 9 | if isinstance(json, dict): 10 | json_dict = json 11 | elif isinstance(json, str): 12 | json_dict = json_handler.loads(json) 13 | else: 14 | raise ValueError(Error.unacceptable_json) 15 | 16 | self.date = json_dict.get("date", None) 17 | -------------------------------------------------------------------------------- /balebot/models/server_responses/sequence/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/server_responses/sequence/__init__.py -------------------------------------------------------------------------------- /balebot/models/server_responses/sequence/difference_update.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.fat_seq_update import FatSeqUpdate 4 | from balebot.models.base_models.response_body import ResponseBody 5 | from balebot.models.constants.errors import Error 6 | 7 | 8 | class DifferenceUpdate(ResponseBody): 9 | def __init__(self, json): 10 | if isinstance(json, dict): 11 | json_dict = json 12 | elif isinstance(json, str): 13 | json_dict = json_handler.loads(json) 14 | else: 15 | raise ValueError(Error.unacceptable_json) 16 | 17 | self.seq = json_dict.get("seq", None) 18 | self.updates = [FatSeqUpdate(update) for update in json_dict.get("updates", None)] 19 | self.need_more = json_dict.get("needMore", None) 20 | -------------------------------------------------------------------------------- /balebot/models/server_responses/sequence/get_last_seq_response.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.response_body import ResponseBody 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class GetLastSeqResponse(ResponseBody): 8 | def __init__(self, json): 9 | if isinstance(json, dict): 10 | json_dict = json 11 | elif isinstance(json, str): 12 | json_dict = json_handler.loads(json) 13 | else: 14 | raise ValueError(Error.unacceptable_json) 15 | 16 | self.seq = json_dict.get("seq", None) 17 | 18 | -------------------------------------------------------------------------------- /balebot/models/server_updates/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/models/server_updates/__init__.py -------------------------------------------------------------------------------- /balebot/models/server_updates/bot_read_update_body.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.peer import Peer 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.server_updates.update_body import UpdateBody 7 | 8 | 9 | class BotReadUpdate(UpdateBody): 10 | def __init__(self, json_dict): 11 | if isinstance(json_dict, dict): 12 | json_dict = json_dict 13 | elif isinstance(json_dict, str): 14 | json_dict = json_handler.loads(json_dict) 15 | else: 16 | raise ValueError(Error.unacceptable_json) 17 | 18 | self.peer = Peer.load_from_json(json_dict.get("peer", None)) 19 | self.start_date = json_dict.get("startDate", None) 20 | self.read_date = json_dict.get("readDate", None) 21 | -------------------------------------------------------------------------------- /balebot/models/server_updates/bot_received_update_body.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.peer import Peer 4 | from balebot.models.constants.errors import Error 5 | 6 | from balebot.models.server_updates.update_body import UpdateBody 7 | 8 | 9 | class BotReceivedUpdate(UpdateBody): 10 | def __init__(self, json_dict): 11 | if isinstance(json_dict, dict): 12 | json_dict = json_dict 13 | elif isinstance(json_dict, str): 14 | json_dict = json_handler.loads(json_dict) 15 | else: 16 | raise ValueError(Error.unacceptable_json) 17 | 18 | self.peer = Peer.load_from_json(json_dict.get("peer", None)) 19 | self.start_date = json_dict.get("startDate", None) 20 | self.receive_date = json_dict.get("receiveDate", None) 21 | -------------------------------------------------------------------------------- /balebot/models/server_updates/message_update_body.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.base_models.peer import Peer 4 | from balebot.models.base_models.user_peer import UserPeer 5 | from balebot.models.factories import message_factory 6 | from balebot.models.server_updates.update_body import UpdateBody 7 | from balebot.models.constants.errors import Error 8 | 9 | from balebot.models.base_models.bot_api_quoted_message import BotApiQuotedMessage 10 | 11 | 12 | class MessageUpdate(UpdateBody): 13 | def __init__(self, json_dict): 14 | if isinstance(json_dict, dict): 15 | json_dict = json_dict 16 | elif isinstance(json_dict, str): 17 | json_dict = json_handler.loads(json_dict) 18 | else: 19 | raise ValueError(Error.unacceptable_json) 20 | 21 | self.peer = Peer.load_from_json(json_dict.get("peer", None)) 22 | self.sender_user = UserPeer.load_from_json(json_dict.get("sender", None)) 23 | self.date = json_dict.get("date", None) 24 | self.random_id = json_dict.get("randomId", None) 25 | self.message = message_factory.MessageFactory.create_message(json_dict.get("message", None)) 26 | self.quoted_message = BotApiQuotedMessage(json_dict.get("quotedMessage", None)) if json_dict.get( 27 | "quotedMessage", None) else None 28 | -------------------------------------------------------------------------------- /balebot/models/server_updates/raw_update_body.py: -------------------------------------------------------------------------------- 1 | import json as json_handler 2 | 3 | from balebot.models.server_updates.update_body import UpdateBody 4 | from balebot.models.constants.errors import Error 5 | 6 | 7 | class RawUpdate(UpdateBody): 8 | def __init__(self, json_dict): 9 | if isinstance(json_dict, dict): 10 | json_dict = json_dict 11 | elif isinstance(json_dict, str): 12 | json_dict = json_handler.loads(json_dict) 13 | else: 14 | raise ValueError(Error.unacceptable_json) 15 | 16 | self.data = json_dict.get("data", None) 17 | -------------------------------------------------------------------------------- /balebot/models/server_updates/update_body.py: -------------------------------------------------------------------------------- 1 | class UpdateBody: 2 | pass 3 | -------------------------------------------------------------------------------- /balebot/updater.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import pickle 3 | import signal 4 | import traceback 5 | from collections import namedtuple 6 | 7 | import redis 8 | 9 | from balebot.config import Config 10 | from balebot.dispatcher import Dispatcher 11 | from balebot.utils.logger import Logger 12 | 13 | redis_db = redis.StrictRedis(host=Config.redis_host, port=Config.redis_port, db=Config.redis_db) \ 14 | if Config.state_holder else None 15 | BotState = namedtuple('BotState', ['conversation_next_step_handlers', 'conversation_data']) 16 | 17 | 18 | class Updater: 19 | def __init__(self, token, base_url=Config.base_url, loop=None): 20 | 21 | self.logger = Logger.get_logger() 22 | 23 | if not token: 24 | raise ValueError("`token` did't passed") 25 | 26 | if not base_url: 27 | raise ValueError("`base_url` did't passed") 28 | 29 | self.token = token 30 | self.timeout = Config.request_timeout 31 | 32 | self.bale_futures = [] 33 | 34 | self._loop = asyncio.get_event_loop() if not loop else loop 35 | 36 | self.dispatcher = Dispatcher(loop=self._loop, 37 | token=self.token, base_url=base_url, 38 | bale_futures=self.bale_futures) 39 | 40 | self.running = False 41 | 42 | def run(self, stop_after=None): 43 | signal.signal(signal.SIGTERM, self.stop) 44 | if Config.state_holder: 45 | bot_previous_state = redis_db.get(self.token) 46 | bot_previous_state = pickle.loads(bot_previous_state) if bot_previous_state else None 47 | self.dispatcher.conversation_next_step_handlers, self.dispatcher.conversation_data = \ 48 | (bot_previous_state.conversation_next_step_handlers, bot_previous_state.conversation_data) \ 49 | if bot_previous_state else ({}, {}) 50 | 51 | asyncio.ensure_future(self._run_dispatcher()) 52 | asyncio.ensure_future(self.dispatcher.bot.network.run()) 53 | 54 | try: 55 | if isinstance(stop_after, int) or isinstance(stop_after, float): 56 | self._stop_after(stop_after) 57 | 58 | self._loop.run_forever() 59 | 60 | except Exception as e: 61 | self.logger.error("exception : {} , {}".format(type(e), e), extra={"tag": "err"}) 62 | traceback.print_exc() 63 | finally: 64 | self.stop() 65 | 66 | def stop(self): 67 | if Config.state_holder: 68 | redis_db.set(self.token, pickle.dumps( 69 | BotState(conversation_next_step_handlers=self.dispatcher.conversation_next_step_handlers, 70 | conversation_data=self.dispatcher.conversation_data))) 71 | self.dispatcher.bot.network.stop_network() 72 | self._stop_dispatcher() 73 | self._loop.stop() 74 | 75 | def _run_dispatcher(self): 76 | return self.dispatcher.run() 77 | 78 | def _stop_dispatcher(self): 79 | self.dispatcher.stop() 80 | 81 | def _stop_after(self, delay): 82 | self._loop.call_later(delay=delay, callback=self.stop) 83 | 84 | def network_connected(self): 85 | return self.dispatcher.bot.network.connected() 86 | 87 | def connect_network(self): 88 | asyncio.ensure_future(self.dispatcher.bot.network.connect()) 89 | -------------------------------------------------------------------------------- /balebot/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/balebot/utils/__init__.py -------------------------------------------------------------------------------- /balebot/utils/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import graypy 3 | 4 | from balebot.config import Config 5 | 6 | 7 | class Logger: 8 | logger = None 9 | 10 | @staticmethod 11 | def init_logger(): 12 | 13 | use_graylog = Config.use_graylog 14 | source = Config.source 15 | graylog_host = Config.graylog_host 16 | graylog_port = Config.graylog_port 17 | log_level = Config.log_level 18 | log_facility_name = Config.log_facility_name 19 | 20 | temp_logger = logging.getLogger(log_facility_name) 21 | temp_logger.setLevel(log_level) 22 | 23 | log_handlers = [] 24 | 25 | if use_graylog == "0": 26 | handler = logging.StreamHandler() 27 | formatter = logging.Formatter( 28 | '%(asctime)s %(filename)s:%(lineno)d %(levelname)s:\n"%(message)s"' 29 | ) 30 | handler.setFormatter(formatter) 31 | log_handlers.append(handler) 32 | 33 | elif use_graylog == "1" and graylog_host and source and graylog_port is not None \ 34 | and isinstance(graylog_port, int): 35 | log_handlers.append(graypy.GELFHandler(host=graylog_host, port=graylog_port, localname=source)) 36 | 37 | elif use_graylog == "2" and graylog_host and source and graylog_port is not None \ 38 | and isinstance(graylog_port, int): 39 | handler1 = graypy.GELFHandler(host=graylog_host, port=graylog_port, localname=source) 40 | 41 | handler2 = logging.StreamHandler() 42 | formatter = logging.Formatter( 43 | '%(asctime)s %(filename)s:%(lineno)d %(levelname)s:\n"%(message)s"' 44 | ) 45 | handler2.setFormatter(formatter) 46 | 47 | log_handlers.append(handler1) 48 | log_handlers.append(handler2) 49 | 50 | for log_handler in log_handlers: 51 | temp_logger.addHandler(log_handler) 52 | 53 | Logger.logger = temp_logger 54 | return Logger.logger 55 | 56 | @staticmethod 57 | def get_logger(): 58 | if Logger.logger: 59 | return Logger.logger 60 | else: 61 | return Logger.init_logger() 62 | -------------------------------------------------------------------------------- /balebot/utils/util_functions.py: -------------------------------------------------------------------------------- 1 | import math 2 | import random 3 | import binascii 4 | from io import BufferedReader 5 | import re 6 | 7 | 8 | def generate_random_id(): 9 | return str(math.floor(random.random() * 1800000)) + str(math.floor(random.random() * 4000000)) + str( 10 | math.floor(random.random() * 55000)) 11 | 12 | 13 | def get_file_buffer(file, file_operation_mode="rb"): 14 | if isinstance(file, str): 15 | opened_file = open(file, file_operation_mode) 16 | buffer = opened_file.read() 17 | opened_file.close() 18 | elif isinstance(file, BufferedReader): 19 | buffer = file.read() 20 | file.close() 21 | elif isinstance(file, bytes): 22 | buffer = file 23 | else: 24 | return None 25 | 26 | return buffer 27 | 28 | 29 | def get_file_size(file): 30 | buffer = get_file_buffer(file=file) 31 | return len(buffer) 32 | 33 | 34 | def get_file_crc32(file): 35 | buffer = get_file_buffer(file=file) 36 | crc_buffer = (binascii.crc32(buffer) & 0xFFFFFFFF) 37 | return crc_buffer 38 | 39 | 40 | def get_image_thumbnails(im): 41 | from io import BytesIO 42 | import base64 43 | from PIL import Image 44 | size = 80, 80 45 | im.thumbnail(size, Image.ANTIALIAS) 46 | output = BytesIO() 47 | im.save(output, format='JPEG') 48 | im_data = output.getvalue() 49 | thumb = '{}'.format(base64.b64encode(im_data).decode()) 50 | return thumb 51 | 52 | 53 | def arabic_to_eng_number(number): 54 | number = str(number) 55 | return number.translate(str.maketrans('۰۱۲۳۴۵۶۷۸۹٠١٢٣٤٥٦٧٨٩', '01234567890123456789')) 56 | 57 | 58 | def eng_to_arabic_number(number): 59 | number = str(number) 60 | return number.translate(str.maketrans('0123456789', '۰۱۲۳۴۵۶۷۸۹')) 61 | 62 | 63 | def phone_number_validation(phone_num): 64 | if re.match(r'^(\+98|0098|0)?9\d{9}$', phone_num): 65 | return True 66 | else: 67 | return False 68 | 69 | 70 | def standardize_phone_number(number): 71 | number_str = str(number) 72 | if number_str.startswith("0098"): 73 | return "+98" + number_str[4:] 74 | elif number_str.startswith("0"): 75 | return "+98" + number_str[1:] 76 | -------------------------------------------------------------------------------- /examples/assets/happy-bot.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/examples/assets/happy-bot.jpeg -------------------------------------------------------------------------------- /examples/assets/image_3200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/examples/assets/image_3200.png -------------------------------------------------------------------------------- /examples/assets/image_3370.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/examples/assets/image_3370.png -------------------------------------------------------------------------------- /examples/assets/image_6450.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/examples/assets/image_6450.png -------------------------------------------------------------------------------- /examples/assets/image_7450.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/examples/assets/image_7450.png -------------------------------------------------------------------------------- /examples/assets/image_7890.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/examples/assets/image_7890.png -------------------------------------------------------------------------------- /examples/assets/image_9390.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/examples/assets/image_9390.png -------------------------------------------------------------------------------- /examples/bank_receipt_conversation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Bank message conversation with bot.""" 5 | import asyncio 6 | 7 | from balebot.filters import * 8 | from balebot.filters.bank_message_filter import BankMessageFilter 9 | from balebot.handlers import MessageHandler 10 | from balebot.models.messages import * 11 | from balebot.models.messages.banking.money_request_type import MoneyRequestType 12 | from balebot.updater import Updater 13 | from balebot.utils.logger import Logger 14 | 15 | # Bale Bot Authorization Token 16 | updater = Updater(token="TOKEN", 17 | loop=asyncio.get_event_loop()) 18 | dispatcher = updater.dispatcher 19 | 20 | # Enable logging 21 | logger = Logger.get_logger() 22 | 23 | 24 | def success_send_message(response, user_data): 25 | logger.info("Your message has been sent successfully.", extra={"tag": "info"}) 26 | 27 | 28 | def failure_send_message(response, user_data): 29 | logger.error("Sending message has been failed", extra={"tag": "error"}) 30 | 31 | 32 | @dispatcher.command_handler(["/start"]) 33 | def conversation_starter(bot, update): 34 | message = TextMessage("Hi , nice to meet you :)\nplease send me a photo") 35 | user_peer = update.get_effective_user() 36 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message) 37 | dispatcher.register_conversation_next_step_handler(update, MessageHandler(PhotoFilter(), purchase_message)) 38 | 39 | 40 | @dispatcher.message_handler(PhotoFilter()) 41 | def purchase_message(bot, update): 42 | message = update.get_effective_message() 43 | user_peer = update.get_effective_user() 44 | first_purchase_message = PurchaseMessage(msg=message, account_number=6037991067471130, amount=100, 45 | money_request_type=MoneyRequestType.normal) 46 | bot.send_message(first_purchase_message, user_peer, success_callback=success_send_message, 47 | failure_callback=failure_send_message) 48 | dispatcher.register_conversation_next_step_handler(update, [MessageHandler(BankMessageFilter(), payment), 49 | MessageHandler(DefaultFilter(), default_handler)]) 50 | 51 | 52 | def payment(bot, update): 53 | message = update.get_effective_message() 54 | logger.info(str(message), extra={"tag": "info"}) 55 | success_payment = TextMessage("Thanks, your payment was successful") 56 | bot.reply(update, success_payment, success_callback=success_send_message, failure_callback=failure_send_message) 57 | dispatcher.finish_conversation(update) 58 | 59 | 60 | def default_handler(bot, update): 61 | success_payment = TextMessage("Ops, something goes wrong") 62 | bot.reply(update, success_payment, success_callback=success_send_message, failure_callback=failure_send_message) 63 | dispatcher.finish_conversation(update) 64 | 65 | 66 | if __name__ == '__main__': 67 | updater.run() 68 | -------------------------------------------------------------------------------- /examples/contact_conversation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Contact message conversation with bot.""" 5 | import asyncio 6 | 7 | from balebot.filters import * 8 | from balebot.handlers import MessageHandler 9 | from balebot.models.messages import * 10 | from balebot.models.messages.contact_message import ContactMessage 11 | from balebot.updater import Updater 12 | from balebot.utils.logger import Logger 13 | 14 | # Bale Bot Authorization Token 15 | updater = Updater(token="TOKEN", 16 | loop=asyncio.get_event_loop()) 17 | dispatcher = updater.dispatcher 18 | 19 | # Enable logging 20 | logger = Logger.get_logger() 21 | 22 | 23 | def success_send_message(response, user_data): 24 | logger.info("Your message has been sent successfully.", extra={"tag": "info"}) 25 | 26 | 27 | def failure_send_message(response, user_data): 28 | logger.error("Sending message has been failed", extra={"tag": "error"}) 29 | 30 | 31 | @dispatcher.message_handler(filters=ContactFilter()) # filter text the client enter to bot 32 | def conversation_starter(bot, update): 33 | user_peer = update.get_effective_user() 34 | general_message = TextMessage("Hi ,I receive your contact, Can I send you a contact too?") 35 | btn_list = [TemplateMessageButton(text="yes", value="yes", action=0), 36 | TemplateMessageButton(text="no", value="no", action=0)] 37 | template_message = TemplateMessage(general_message=general_message, btn_list=btn_list) 38 | bot.send_message(template_message, user_peer, success_callback=success_send_message, 39 | failure_callback=failure_send_message) 40 | dispatcher.register_conversation_next_step_handler( 41 | update, [MessageHandler(TemplateResponseFilter(keywords=["yes"]), send_contact), 42 | MessageHandler(TemplateResponseFilter(keywords=["no"]), no_thanks)]) 43 | 44 | 45 | def no_thanks(bot, update): 46 | bot.reply(update, "It's Ok.", success_callback=success_send_message, failure_callback=failure_send_message) 47 | dispatcher.finish_conversation(update) 48 | 49 | 50 | def send_contact(bot, update): 51 | user_peer = update.get_effective_user() 52 | bot.respond(update, "Here is a contact for you.", success_callback=success_send_message, 53 | failure_callback=failure_send_message) 54 | contact_message = ContactMessage(name="test contact", emails=["test@test.com"], phones=["09123456789"]) 55 | bot.send_message(contact_message, user_peer, success_callback=success_send_message, 56 | failure_callback=failure_send_message) 57 | dispatcher.finish_conversation(update) 58 | 59 | 60 | if __name__ == '__main__': 61 | updater.run() 62 | -------------------------------------------------------------------------------- /examples/echobot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Simple Bot to reply to Bale messages. 5 | 6 | This Bot uses the Updater class to handle the bot. 7 | 8 | First, a few handler functions are defined. Then, those functions are passed to 9 | the Dispatcher and registered at their respective places. 10 | Then, the bot is started and runs until we press Ctrl-C on the command line. 11 | 12 | Usage: 13 | Basic Echobot example, repeats messages. 14 | Press Ctrl-C on the command line or send a signal to the process to stop the 15 | bot. 16 | """ 17 | 18 | from balebot.filters import DefaultFilter 19 | from balebot.handlers import CommandHandler, MessageHandler 20 | from balebot.updater import Updater 21 | from balebot.utils.logger import Logger 22 | 23 | # Enable logging 24 | logger = Logger.get_logger() 25 | 26 | 27 | # Define a few command handlers. These usually take the two arguments bot and 28 | def start(bot, update): 29 | """Send a message when the command /start is issued.""" 30 | bot.reply(update, 'Hi!') 31 | 32 | 33 | def help(bot, update): 34 | """Send a message when the command /help is issued.""" 35 | bot.reply(update, 'Help!') 36 | 37 | 38 | def echo(bot, update): 39 | """Echo the user message.""" 40 | message = update.get_effective_message() 41 | bot.reply(update, message) 42 | 43 | 44 | def error(bot, update, error): 45 | """Log Errors caused by Updates.""" 46 | logger.error('Update {} caused error {}'.format(update, error), extra={"tag": "err"}) 47 | 48 | 49 | def main(): 50 | """Start the bot.""" 51 | # Bale Bot Authorization Token 52 | updater = Updater("TOKEN") 53 | 54 | # Get the dispatcher to register handlers 55 | dp = updater.dispatcher 56 | 57 | # on different commands - answer in Bale 58 | dp.add_handler(CommandHandler("start", start)) 59 | dp.add_handler(CommandHandler("help", help)) 60 | 61 | # on noncommand i.e message - echo the message on Bale 62 | dp.add_handler(MessageHandler(DefaultFilter(), echo)) 63 | 64 | # log all errors 65 | dp.add_error_handler(error) 66 | 67 | # Start the Bot 68 | updater.run() 69 | 70 | 71 | if __name__ == '__main__': 72 | main() 73 | -------------------------------------------------------------------------------- /examples/location_conversation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Location message conversation with bot.""" 5 | import asyncio 6 | 7 | from balebot.filters import * 8 | from balebot.handlers import MessageHandler 9 | from balebot.models.messages import * 10 | from balebot.models.messages.location_message import LocationMessage 11 | from balebot.updater import Updater 12 | from balebot.utils.logger import Logger 13 | 14 | # Bale Bot Authorization Token 15 | updater = Updater(token="TOKEN", 16 | loop=asyncio.get_event_loop()) 17 | dispatcher = updater.dispatcher 18 | 19 | # Enable logging 20 | logger = Logger.get_logger() 21 | 22 | 23 | def success_send_message(response, user_data): 24 | logger.info("Your message has been sent successfully.", extra={"tag": "info"}) 25 | 26 | 27 | def failure_send_message(response, user_data): 28 | logger.error("Sending message has been failed", extra={"tag": "error"}) 29 | 30 | 31 | @dispatcher.message_handler(filters=LocationFilter()) 32 | def conversation_starter(bot, update): 33 | user_peer = update.get_effective_user() 34 | general_message = TextMessage("Hi ,Are you hungry?") 35 | btn_list = [TemplateMessageButton(text="yes", value="yes", action=0), 36 | TemplateMessageButton(text="no", value="no", action=0)] 37 | template_message = TemplateMessage(general_message=general_message, btn_list=btn_list) 38 | bot.send_message(template_message, user_peer, success_callback=success_send_message, 39 | failure_callback=failure_send_message) 40 | dispatcher.register_conversation_next_step_handler( 41 | update, [MessageHandler(TemplateResponseFilter(keywords=["yes"]), find_location), 42 | MessageHandler(TemplateResponseFilter(keywords=["no"]), no_thanks)]) 43 | 44 | 45 | def no_thanks(bot, update): 46 | bot.reply(update, "It's Ok.", success_callback=success_send_message, failure_callback=failure_send_message) 47 | dispatcher.finish_conversation(update) 48 | 49 | 50 | def find_location(bot, update): 51 | user_peer = update.get_effective_user() 52 | bot.reply(update, "Here is a good restaurant sir.", success_callback=success_send_message, 53 | failure_callback=failure_send_message) 54 | # Make a location from LocationMessage and send it. 55 | location_message = LocationMessage(longitude="51.41714821748457", latitude="35.73122955392002") 56 | bot.send_message(location_message, user_peer, success_callback=success_send_message, 57 | failure_callback=failure_send_message) 58 | dispatcher.finish_conversation(update) 59 | 60 | 61 | if __name__ == '__main__': 62 | updater.run() 63 | -------------------------------------------------------------------------------- /examples/photo_voice_conversation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Voice and Photo simple conversation with bot.""" 5 | import asyncio 6 | 7 | from balebot.filters import * 8 | from balebot.handlers import MessageHandler 9 | from balebot.models.messages import * 10 | from balebot.updater import Updater 11 | from balebot.utils.logger import Logger 12 | 13 | # Bale Bot Authorization Token 14 | updater = Updater(token="TOKEN", 15 | loop=asyncio.get_event_loop()) 16 | dispatcher = updater.dispatcher 17 | 18 | # Enable logging 19 | logger = Logger.get_logger() 20 | 21 | 22 | def success_send_message(response, user_data): 23 | kwargs = user_data['kwargs'] 24 | update = kwargs["update"] 25 | user_peer = update.get_effective_user() 26 | logger.info("Your message has been sent successfully.", extra={"user_id": user_peer.peer_id, "tag": "info"}) 27 | 28 | 29 | def failure_send_message(response, user_data): 30 | kwargs = user_data['kwargs'] 31 | update = kwargs["update"] 32 | user_peer = update.get_effective_user() 33 | logger.error("Sending message has been failed", extra={"user_id": user_peer.peer_id, "tag": "error"}) 34 | 35 | 36 | @dispatcher.command_handler(["/start"]) 37 | def conversation_starter(bot, update): 38 | message = TextMessage("Hi , nice to meet you :)" 39 | "\nif you want to see my photo," 40 | "\nsend me a *voice*") 41 | user_peer = update.get_effective_user() 42 | kwargs = {'update': update} 43 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 44 | kwargs=kwargs) 45 | dispatcher.register_conversation_next_step_handler(update, [MessageHandler(VoiceFilter(), get_voice), 46 | MessageHandler(DefaultFilter(), skip_voice)]) 47 | 48 | 49 | @dispatcher.message_handler(VoiceFilter()) 50 | def get_voice(bot, update): 51 | user_peer = update.get_effective_user() 52 | kwargs = {'update': update} 53 | 54 | def success_send_photo_message(result, user_data): 55 | message = TextMessage("Hahahaha! It's me." 56 | "\nNow It's your turn." 57 | "\nSend me your photo:") 58 | bot.send_message(message, user_peer, success_callback=success_send_message, 59 | failure_callback=failure_send_message, kwargs=kwargs) 60 | dispatcher.register_conversation_next_step_handler(update, MessageHandler(PhotoFilter(), finish_conversion)) 61 | 62 | bot.send_photo(user_peer=user_peer, image="./assets/happy-bot.jpeg", caption_text="caption comes here!", 63 | name="bale.jpg", file_storage_version=1, mime_type="image/jpeg", 64 | success_callback=success_send_photo_message) 65 | 66 | 67 | def skip_voice(bot, update): 68 | message = TextMessage("So, It seems you don't like to send me 'Hello' voice!" 69 | "\nplease just give me your photo.") 70 | user_peer = update.get_effective_user() 71 | kwargs = {'update': update} 72 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 73 | kwargs=kwargs) 74 | dispatcher.register_conversation_next_step_handler(update, MessageHandler(PhotoFilter(), finish_conversion)) 75 | 76 | 77 | def finish_conversion(bot, update): 78 | user_peer = update.get_effective_user() 79 | photo_message_given = update.get_effective_message() 80 | kwargs = {'update': update} 81 | bot.reply(update, photo_message_given, success_callback=success_send_message, failure_callback=failure_send_message, 82 | kwargs=kwargs) 83 | message = TextMessage("Thanks \ngoodbye ;)") 84 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 85 | kwargs=kwargs) 86 | dispatcher.finish_conversation(update) 87 | 88 | 89 | if __name__ == '__main__': 90 | updater.run() 91 | -------------------------------------------------------------------------------- /examples/purchase_conversation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Purchase message simple conversation with bot.""" 5 | import asyncio 6 | 7 | from balebot.filters import * 8 | from balebot.handlers import MessageHandler 9 | from balebot.models.messages import * 10 | from balebot.models.messages.banking.money_request_type import MoneyRequestType 11 | from balebot.updater import Updater 12 | from balebot.utils.logger import Logger 13 | 14 | # Bale Bot Authorization Token 15 | updater = Updater(token="TOKEN", 16 | loop=asyncio.get_event_loop()) 17 | dispatcher = updater.dispatcher 18 | 19 | # Enable logging 20 | logger = Logger.get_logger() 21 | 22 | 23 | def success_send_message(response, user_data): 24 | kwargs = user_data['kwargs'] 25 | update = kwargs["update"] 26 | user_peer = update.get_effective_user() 27 | logger.info("Your message has been sent successfully.", extra={"user_id": user_peer.peer_id, "tag": "info"}) 28 | 29 | 30 | def failure_send_message(response, user_data): 31 | kwargs = user_data['kwargs'] 32 | update = kwargs["update"] 33 | user_peer = update.get_effective_user() 34 | logger.error("Sending message has been failed", extra={"user_id": user_peer.peer_id, "tag": "error"}) 35 | 36 | 37 | @dispatcher.command_handler(["/start"]) 38 | def conversation_starter(bot, update): 39 | message = TextMessage("Hi , nice to meet you :)\nplease send me a photo") 40 | user_peer = update.get_effective_user() 41 | kwargs = {'update': update} 42 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 43 | kwargs=kwargs) 44 | dispatcher.register_conversation_next_step_handler(update, MessageHandler(PhotoFilter(), purchase_message)) 45 | 46 | 47 | @dispatcher.message_handler(PhotoFilter()) 48 | def purchase_message(bot, update): 49 | message = update.get_effective_message() 50 | user_peer = update.get_effective_user() 51 | purchase_message = PurchaseMessage(msg=message, account_number=6037991067471130, amount=10, 52 | money_request_type=MoneyRequestType.normal) 53 | kwargs = {'update': update} 54 | bot.send_message(purchase_message, user_peer, success_callback=success_send_message, 55 | failure_callback=failure_send_message, kwargs=kwargs) 56 | dispatcher.finish_conversation(update) 57 | 58 | 59 | @dispatcher.message_handler(BankMessageFilter()) 60 | def handle_receipt(bot, update): 61 | bank_message = update.get_effective_message() 62 | user_peer = update.get_effective_user() 63 | receipt = bank_message.get_receipt() 64 | kwargs = {'update': update} 65 | message = TextMessage("your payment receipt received with trace Number: {}".format(receipt.traceNo)) 66 | bot.send_message(message, user_peer, success_callback=success_send_message, 67 | failure_callback=failure_send_message, kwargs=kwargs) 68 | logger.info(receipt, extra={"tag": "info"}) 69 | logger.info(receipt.payer, receipt.msgUID, extra={"tag": "info"}) 70 | 71 | 72 | if __name__ == '__main__': 73 | updater.run() 74 | -------------------------------------------------------------------------------- /examples/quoted_message_conversation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """QuotedMessage conversation with bot.""" 5 | import asyncio 6 | 7 | from balebot.filters import * 8 | from balebot.handlers import QuotedMessageHandler 9 | from balebot.models.messages import * 10 | from balebot.updater import Updater 11 | from balebot.utils.logger import Logger 12 | 13 | # Bale Bot Authorization Token 14 | updater = Updater(token="TOKEN", 15 | loop=asyncio.get_event_loop()) 16 | dispatcher = updater.dispatcher 17 | 18 | # Enable logging 19 | logger = Logger.get_logger() 20 | 21 | 22 | def success_send_message(response, user_data): 23 | kwargs = user_data['kwargs'] 24 | update = kwargs["update"] 25 | user_peer = update.get_effective_user() 26 | logger.info("Your message has been sent successfully.", extra={"user_id": user_peer.peer_id, "tag": "info"}) 27 | 28 | 29 | def failure_send_message(response, user_data): 30 | kwargs = user_data['kwargs'] 31 | update = kwargs["update"] 32 | user_peer = update.get_effective_user() 33 | logger.error("Sending message has been failed", extra={"user_id": user_peer.peer_id, "tag": "error"}) 34 | 35 | 36 | @dispatcher.command_handler(["/start"]) 37 | def conversation_starter(bot, update): 38 | message = TextMessage("*Hi , nice to meet you*\nplease forward a message to me.") 39 | user_peer = update.get_effective_user() 40 | kwargs = {"message": message, "update": update} 41 | bot.send_message(message, user_peer, success_callback=success_send_message, 42 | failure_callback=failure_send_message, kwargs=kwargs) 43 | dispatcher.register_conversation_next_step_handler( 44 | update, [QuotedMessageHandler(DefaultFilter(), echo_quoted)]) 45 | 46 | 47 | @dispatcher.quoted_message_handler(DefaultFilter()) 48 | def echo_quoted(bot, update): 49 | user_peer = update.get_effective_user() 50 | kwargs = {'update': update} 51 | quoted_sender_id = update.get_quoted_sender_peer_id() 52 | logger.debug("replied or forwarded message from peer_id: " + str(quoted_sender_id), extra={"tag": "debug"}) 53 | output = update.get_quoted_message() 54 | bot.send_message(output, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 55 | kwargs=kwargs) 56 | dispatcher.finish_conversation(update) 57 | 58 | 59 | if __name__ == '__main__': 60 | updater.run() 61 | -------------------------------------------------------------------------------- /examples/simple_edit_message.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Simple Bot to edit Bale messages.""" 5 | 6 | import asyncio 7 | 8 | from balebot.models.messages import TextMessage 9 | from balebot.updater import Updater 10 | from balebot.utils.logger import Logger 11 | 12 | # Bale Bot Authorization Token 13 | 14 | updater = Updater(token="TOKEN", 15 | loop=asyncio.get_event_loop()) 16 | # Define dispatcher 17 | dispatcher = updater.dispatcher 18 | 19 | # Enable logging 20 | logger = Logger.get_logger() 21 | 22 | 23 | # Both of success and failure functions are optional 24 | def success_send_message(response, user_data): 25 | kwargs = user_data['kwargs'] 26 | update = kwargs["update"] 27 | user_peer = update.get_effective_user() 28 | logger.info("Your message has been sent successfully.", extra={"user_id": user_peer.peer_id, "tag": "info"}) 29 | 30 | 31 | def failure_send_message(response, user_data): 32 | kwargs = user_data['kwargs'] 33 | update = kwargs["update"] 34 | user_peer = update.get_effective_user() 35 | logger.error("Sending message has been failed", extra={"user_id": user_peer.peer_id, "tag": "error"}) 36 | 37 | 38 | def success_edit_message(response, user_data): 39 | logger.info("Your message has been edited successfully.", extra={"tag": "info"}) 40 | 41 | 42 | def failure_edit_message(response, user_data): 43 | logger.error("Editing message has been failed", extra={"tag": "error"}) 44 | 45 | 46 | request_random_id = None 47 | 48 | 49 | @dispatcher.command_handler(commands='/start') 50 | def start(bot, update): 51 | message = TextMessage('*Hello this message will be edited when you send /edit command*') 52 | # Send a message to client 53 | kwargs = {"update": update} 54 | request = bot.respond(update, message, success_callback=success_send_message, failure_callback=failure_send_message, 55 | kwargs=kwargs) 56 | global request_random_id 57 | request_random_id = request.get_json_object()['body']['randomId'] 58 | logger.debug(request_random_id, extra={"tag": "debug"}) 59 | 60 | 61 | @dispatcher.command_handler(commands='/edit') 62 | def edit(bot, update): 63 | user_peer = update.get_effective_user() 64 | message = TextMessage('*message edited*') 65 | # edit nd a message to client 66 | bot.edit_message(message=message, user_peer=user_peer, random_id=request_random_id, 67 | success_callback=success_edit_message, failure_callback=failure_edit_message) 68 | 69 | 70 | # Run the bot! 71 | if __name__ == '__main__': 72 | updater.run() 73 | -------------------------------------------------------------------------------- /examples/template_message_conversation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Template simple conversation with bot.""" 5 | import asyncio 6 | 7 | from balebot.filters import * 8 | from balebot.handlers import MessageHandler, CommandHandler 9 | from balebot.models.messages import * 10 | from balebot.updater import Updater 11 | from balebot.utils.logger import Logger 12 | 13 | # Bale Bot Authorization Token 14 | updater = Updater(token="TOKEN", 15 | loop=asyncio.get_event_loop()) 16 | dispatcher = updater.dispatcher 17 | 18 | # Enable logging 19 | logger = Logger.get_logger() 20 | 21 | 22 | def success_send_message(response, user_data): 23 | kwargs = user_data['kwargs'] 24 | update = kwargs["update"] 25 | user_peer = update.get_effective_user() 26 | logger.info("Your message has been sent successfully.", extra={"user_id": user_peer.peer_id, "tag": "info"}) 27 | 28 | 29 | def failure_send_message(response, user_data): 30 | kwargs = user_data['kwargs'] 31 | update = kwargs["update"] 32 | user_peer = update.get_effective_user() 33 | logger.error("Sending message has been failed", extra={"user_id": user_peer.peer_id, "tag": "error"}) 34 | 35 | 36 | @dispatcher.command_handler(["/start"]) 37 | def conversation_starter(bot, update): 38 | message = TextMessage("*Hi , come try a interesting message* \nplease tell me a *yes-no* question.") 39 | user_peer = update.get_effective_user() 40 | kwargs = {"update": update} 41 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 42 | kwargs=kwargs) 43 | dispatcher.register_conversation_next_step_handler(update, MessageHandler(TextFilter(), ask_question)) 44 | 45 | 46 | def ask_question(bot, update): 47 | user_peer = update.get_effective_user() 48 | my_message = TextMessage("*Your Template Message created!*") 49 | kwargs = {"update": update} 50 | bot.send_message(my_message, user_peer, success_callback=success_send_message, 51 | failure_callback=failure_send_message, kwargs=kwargs) 52 | # Set client message as general message of a template message 53 | general_message = update.get_effective_message() 54 | # Create how many buttons you like with TemplateMessageButton class 55 | btn_list = [TemplateMessageButton(text="yes", value="yes", action=0), 56 | TemplateMessageButton(text="no", value="no", action=0)] 57 | # Create a Template Message 58 | template_message = TemplateMessage(general_message=general_message, btn_list=btn_list) 59 | bot.send_message(template_message, user_peer, success_callback=success_send_message, 60 | failure_callback=failure_send_message, kwargs=kwargs) 61 | dispatcher.register_conversation_next_step_handler( 62 | update, [MessageHandler(TemplateResponseFilter(keywords=["yes"]), positive_answer), 63 | MessageHandler(TemplateResponseFilter(keywords=["no"]), negative_answer)]) 64 | 65 | 66 | # Use when answer is 'yes' 67 | def positive_answer(bot, update): 68 | message = TextMessage("*Your have answered 'yes'* \n" 69 | "end the conversion with below command: \n" 70 | "[/end](send:/end)") 71 | user_peer = update.get_effective_user() 72 | kwargs = {"update": update} 73 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 74 | kwargs=kwargs) 75 | # Use CommandHandler to handle a command which is sent by client 76 | dispatcher.register_conversation_next_step_handler(update, CommandHandler("/end", finish_conversion)) 77 | 78 | 79 | # Use when answer is 'no' 80 | def negative_answer(bot, update): 81 | message = TextMessage("*Your have answered 'no'* \n" 82 | "Write a new question or end the conversion with below command: \n" 83 | "[/end](send:/end)") 84 | user_peer = update.get_effective_user() 85 | kwargs = {"update": update} 86 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 87 | kwargs=kwargs) 88 | dispatcher.register_conversation_next_step_handler(update, [CommandHandler("/end", finish_conversion)]) 89 | 90 | 91 | def finish_conversion(bot, update): 92 | message = TextMessage("*Thanks* \ngoodbye ;)") 93 | user_peer = update.get_effective_user() 94 | kwargs = {"update": update} 95 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 96 | kwargs=kwargs) 97 | # Finish conversation 98 | dispatcher.finish_conversation(update) 99 | 100 | 101 | if __name__ == '__main__': 102 | updater.run() 103 | -------------------------------------------------------------------------------- /examples/text_conversation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Text simple conversation with bot.""" 5 | import asyncio 6 | 7 | from balebot.filters import * 8 | from balebot.handlers import MessageHandler 9 | from balebot.models.messages import * 10 | from balebot.updater import Updater 11 | from balebot.utils.logger import Logger 12 | 13 | # Bale Bot Authorization Token 14 | updater = Updater(token="TOKEN", 15 | loop=asyncio.get_event_loop()) 16 | dispatcher = updater.dispatcher 17 | 18 | # Enable logging 19 | logger = Logger.get_logger() 20 | 21 | 22 | def success_send_message(response, user_data): 23 | kwargs = user_data['kwargs'] 24 | update = kwargs["update"] 25 | user_peer = update.get_effective_user() 26 | logger.info("Your message has been sent successfully.", extra={"user_id": user_peer.peer_id, "tag": "info"}) 27 | 28 | 29 | def failure_send_message(response, user_data): 30 | kwargs = user_data['kwargs'] 31 | update = kwargs["update"] 32 | user_peer = update.get_effective_user() 33 | logger.error("Sending message has been failed", extra={"user_id": user_peer.peer_id, "tag": "error"}) 34 | 35 | 36 | @dispatcher.command_handler(["/start"]) 37 | def conversation_starter(bot, update): 38 | message = TextMessage("*Hi , nice to meet you*\nplease tell me your name.") 39 | # Get client user object by a function called (get_effective_user) 40 | user_peer = update.get_effective_user() 41 | # Set any user data in kwargs mode 42 | kwargs = {"message": message, "update": update} 43 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 44 | kwargs=kwargs) 45 | # You can put more than one Filters for your handler 46 | dispatcher.register_conversation_next_step_handler(update, [MessageHandler(TextFilter(), ask_name), 47 | MessageHandler(DefaultFilter(), skip_name)]) 48 | 49 | 50 | def ask_name(bot, update): 51 | message = TextMessage("*Thanks!*\nplease tell me your age") 52 | user_peer = update.get_effective_user() 53 | # Get client message object by a function called (get_effective_message) 54 | name_obj = update.get_effective_message() 55 | # Get text form a message obj 56 | name_text = name_obj.text 57 | # Set a conversation data in RAM (Not durable) 58 | dispatcher.set_conversation_data(update=update, key="name", value=name_text) 59 | kwargs = {"message": message, "update": update} 60 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 61 | kwargs=kwargs) 62 | dispatcher.register_conversation_next_step_handler(update, 63 | # Set Regex pattern for TextFilter 64 | MessageHandler(TextFilter(pattern="^[0-9]+$"), 65 | finish_conversion)) 66 | 67 | 68 | def skip_name(bot, update): 69 | message = TextMessage("*So, you don't want to tell your name!*\nplease just tell me your age") 70 | user_peer = update.get_effective_user() 71 | kwargs = {'update': update} 72 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 73 | kwargs=kwargs) 74 | no_name = "no name" 75 | dispatcher.set_conversation_data(update=update, key="name", value=no_name) 76 | dispatcher.register_conversation_next_step_handler(update, MessageHandler(TextFilter(), finish_conversion)) 77 | 78 | 79 | def finish_conversion(bot, update): 80 | message = TextMessage("*Thanks!*\ngoodbye ;)") 81 | user_peer = update.get_effective_user() 82 | kwargs = {'update': update} 83 | bot.send_message(message, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 84 | kwargs=kwargs) 85 | name = dispatcher.get_conversation_data(update, key="name") 86 | age = update.get_effective_message().text 87 | output = TextMessage("*Name:* " + name + "\n" + "*Age:* " + age) 88 | bot.send_message(output, user_peer, success_callback=success_send_message, failure_callback=failure_send_message, 89 | kwargs=kwargs) 90 | dispatcher.finish_conversation(update) 91 | 92 | 93 | if __name__ == '__main__': 94 | updater.run() 95 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp==2.3.7 2 | async-timeout==2.0.0 3 | asyncio==3.4.3 4 | chardet==3.0.4 5 | graypy==0.2.14 6 | idna==2.6 7 | multidict==3.3.2 8 | yarl==0.17.0 9 | pillow==5.2.0 10 | redis==3.0.1 11 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from setuptools import find_packages, setup 4 | 5 | here = os.path.abspath(os.path.dirname(__file__)) 6 | 7 | requires = [ 8 | 'aiohttp==2.3.7', 9 | 'asyncio==3.4.3', 10 | 'graypy==0.2.14', 11 | 'pillow==5.2.0', 12 | 'redis==3.0.1' 13 | ] 14 | 15 | about = {} 16 | with open(os.path.join(here, 'balebot', '__version__.py'), mode='rt', encoding='utf-8') as f: 17 | exec(f.read(), about) 18 | 19 | setup( 20 | name=about['__title__'], 21 | version=about['__version__'], 22 | description=about['__description__'], 23 | author=about['__author__'], 24 | author_email=about['__author_email__'], 25 | license=about['__license__'], 26 | long_description="\n\n".join([open("README.md").read(), open("CHANGELOG.md").read()]), 27 | long_description_content_type='text/markdown', 28 | url=about['__url__'], 29 | install_requires=requires, 30 | packages=find_packages(), 31 | ) 32 | -------------------------------------------------------------------------------- /test_bale_bot/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/test_bale_bot/__init__.py -------------------------------------------------------------------------------- /test_bale_bot/test_bot.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock 3 | 4 | from balebot.models.base_models import Peer 5 | from balebot.models.messages import TextMessage 6 | from balebot.bot import Bot 7 | from balebot.models.base_models import Request 8 | 9 | 10 | class TestBot(unittest.TestCase): 11 | @classmethod 12 | def setUpClass(cls): 13 | cls.bot = MagicMock() 14 | cls.bot.set_future.return_value = None 15 | cls.bot.send_request.return_value = None 16 | 17 | def test_update_message_content(self): 18 | message = TextMessage("ASD") 19 | peer = Peer(peer_type="User", peer_id=1422775695, 20 | access_hash="asdqweqwdasd") 21 | self.assertIsInstance(Bot.edit_message(self.bot, message=message, user_peer=peer, random_id=13246), 22 | Request) 23 | -------------------------------------------------------------------------------- /test_bale_bot/test_models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/test_bale_bot/test_models/__init__.py -------------------------------------------------------------------------------- /test_bale_bot/test_models/test_client_requests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/test_bale_bot/test_models/test_client_requests/__init__.py -------------------------------------------------------------------------------- /test_bale_bot/test_models/test_client_requests/test_messaging/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/test_bale_bot/test_models/test_client_requests/test_messaging/__init__.py -------------------------------------------------------------------------------- /test_bale_bot/test_models/test_client_requests/test_messaging/test_edit_message.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock 3 | 4 | from balebot.models.base_models import Peer 5 | from balebot.models.client_requests import EditMessage 6 | from balebot.models.messages import TextMessage 7 | 8 | 9 | class TestEditMessage(unittest.TestCase): 10 | @classmethod 11 | def setUpClass(cls): 12 | peer = Peer(peer_type="User", peer_id=1422775695, 13 | access_hash="asdqweqwdasd") 14 | message = TextMessage("ASD") 15 | cls.update_request = EditMessage(updated_message=message, peer=peer, random_id=123465) 16 | 17 | def test_get_json_object(self): 18 | self.assertIsInstance(self.update_request.get_json_object(), dict) 19 | 20 | def test_get_json_str(self): 21 | self.assertIsInstance(self.update_request.get_json_str(), str) 22 | -------------------------------------------------------------------------------- /test_bale_bot/test_models/test_resver_responses/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/test_bale_bot/test_models/test_resver_responses/__init__.py -------------------------------------------------------------------------------- /test_bale_bot/test_models/test_resver_responses/test_messaging/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balemessenger/bale-bot-python/b5d66899099fefea5607fd1c25ce0ab1c6a0e5f2/test_bale_bot/test_models/test_resver_responses/test_messaging/__init__.py -------------------------------------------------------------------------------- /test_bale_bot/test_models/test_resver_responses/test_messaging/test_message_edited.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import MagicMock 3 | 4 | from balebot.models.server_responses.messaging.message_edited import MessageEdited 5 | 6 | 7 | class TestMessageEdited(unittest.TestCase): 8 | @classmethod 9 | def setUpClass(cls): 10 | cls.edit_message_response_body = '{"seq":"2090","date":"1536053835915"}' 11 | 12 | def test_message_edited(self): 13 | message_edited_body = MessageEdited(self.edit_message_response_body) 14 | self.assertEqual(message_edited_body.date, '1536053835915') 15 | self.assertEqual(message_edited_body.seq, '2090') 16 | --------------------------------------------------------------------------------