def from_array(array): """ Deserialize a new PreCheckoutQuery from a given dictionary. :return: new PreCheckoutQuery instance. :rtype: PreCheckoutQuery """ if array is None or not array: return None # end if assert_type_or_raise(array, dict, parameter_name="array") from pytgbot.api_types.receivable.peer import User data = {} data['id'] = u(array.get('id')) data['from_peer'] = User.from_array(array.get('from')) data['currency'] = u(array.get('currency')) data['total_amount'] = int(array.get('total_amount')) data['invoice_payload'] = u(array.get('invoice_payload')) data['shipping_option_id'] = u( array.get('shipping_option_id')) if array.get( 'shipping_option_id') is not None else None data['order_info'] = OrderInfo.from_array(array.get( 'order_info')) if array.get('order_info') is not None else None data['_raw'] = array return PreCheckoutQuery(**data)
def __init__(self, host="127.0.0.1", port=4458, telegram=None, pubkey_file=None, custom_cli_args=None): from .sender import Sender from .receiver import Receiver self._proc = None if telegram and pubkey_file: if host not in ["127.0.0.1", "localhost", "", None]: raise ValueError("Can only start the cli at localhost. You may not provide a different host.") host = "127.0.0.1" self.start_cli(telegram=telegram, pubkey_file=pubkey_file, custom_cli_args=custom_cli_args, port=port) elif telegram is not None or pubkey_file is not None or custom_cli_args is not None: logger.warn("cli related parameter given, but not cli and pubkey path not present.") self.sender = Sender(host=host, port=port) self.receiver = Receiver(host=host, port=port) while self._proc is not None and self._proc.returncode is None: self._proc.poll() try: result = self.sender.raw(u("help"), retry_connect=False) if result and u("Prints this help") in result: logger.info("CLI available.") else: logger.warn("CLI does not responde correctly. (Debug: {})".format(result)) break except: logger.info("CLI did not responde.") sleep(1) else: raise AssertionError("CLI Process died.")
def from_array(array): """ Deserialize a new ChosenInlineResult from a given dictionary. :return: new ChosenInlineResult instance. :rtype: ChosenInlineResult """ if array is None or not array: return None # end if assert_type_or_raise(array, dict, parameter_name="array") from pytgbot.api_types.receivable.media import Location from pytgbot.api_types.receivable.peer import User data = {} data['result_id'] = u(array.get('result_id')) data['from_peer'] = User.from_array(array.get('from')) data['query'] = u(array.get('query')) data['location'] = Location.from_array(array.get( 'location')) if array.get('location') is not None else None data['inline_message_id'] = u( array.get('inline_message_id')) if array.get( 'inline_message_id') is not None else None data['_raw'] = array return ChosenInlineResult(**data)
def from_array(array): """ Deserialize a new SuccessfulPayment from a given dictionary. :return: new SuccessfulPayment instance. :rtype: SuccessfulPayment """ if array is None or not array: return None # end if assert_type_or_raise(array, dict, parameter_name="array") data = {} data['currency'] = u(array.get('currency')) data['total_amount'] = int(array.get('total_amount')) data['invoice_payload'] = u(array.get('invoice_payload')) data['telegram_payment_charge_id'] = u( array.get('telegram_payment_charge_id')) data['provider_payment_charge_id'] = u( array.get('provider_payment_charge_id')) data['shipping_option_id'] = u( array.get('shipping_option_id')) if array.get( 'shipping_option_id') is not None else None data['order_info'] = OrderInfo.from_array(array.get( 'order_info')) if array.get('order_info') is not None else None data['_raw'] = array return SuccessfulPayment(**data)
def to_array(self): """ Serializes this SuccessfulPayment to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(SuccessfulPayment, self).to_array() array['currency'] = u( self.currency) # py2: type unicode, py3: type str array['total_amount'] = int(self.total_amount) # type int array['invoice_payload'] = u( self.invoice_payload) # py2: type unicode, py3: type str array['telegram_payment_charge_id'] = u( self.telegram_payment_charge_id ) # py2: type unicode, py3: type str array['provider_payment_charge_id'] = u( self.provider_payment_charge_id ) # py2: type unicode, py3: type str if self.shipping_option_id is not None: array['shipping_option_id'] = u( self.shipping_option_id) # py2: type unicode, py3: type str if self.order_info is not None: array['order_info'] = self.order_info.to_array() # type OrderInfo return array
def from_array(array): """ Deserialize a new EncryptedPassportElement from a given dictionary. :return: new EncryptedPassportElement instance. :rtype: EncryptedPassportElement """ if array is None or not array: return None # end if assert_type_or_raise(array, dict, parameter_name="array") from pytgbot.api_types.receivable.passport import PassportFile data = {} data['type'] = u(array.get('type')) data['data'] = u(array.get('data')) if array.get('data') is not None else None data['phone_number'] = u(array.get('phone_number')) if array.get('phone_number') is not None else None data['email'] = u(array.get('email')) if array.get('email') is not None else None data['files'] = PassportFile.from_array_list(array.get('files'), list_level=1) if array.get('files') is not None else None data['front_side'] = PassportFile.from_array(array.get('front_side')) if array.get('front_side') is not None else None data['reverse_side'] = PassportFile.from_array(array.get('reverse_side')) if array.get('reverse_side') is not None else None data['selfie'] = PassportFile.from_array(array.get('selfie')) if array.get('selfie') is not None else None data['_raw'] = array return EncryptedPassportElement(**data)
def from_array(array): """ Deserialize a new InputMediaVideo from a given dictionary. :return: new InputMediaVideo instance. :rtype: InputMediaVideo """ if array is None or not array: return None # end if assert_type_or_raise(array, dict, parameter_name="array") data = {} data['type'] = u(array.get('type')) data['media'] = u(array.get('media')) data['caption'] = u( array.get('caption')) if array.get('caption') is not None else None data['parse_mode'] = u(array.get('parse_mode')) if array.get( 'parse_mode') is not None else None data['width'] = int( array.get('width')) if array.get('width') is not None else None data['height'] = int( array.get('height')) if array.get('height') is not None else None data['duration'] = int(array.get('duration')) if array.get( 'duration') is not None else None data['supports_streaming'] = bool( array.get('supports_streaming')) if array.get( 'supports_streaming') is not None else None instance = InputMediaVideo(**data) instance._raw = array return instance
def to_array(self): """ Serializes this InlineKeyboardButton to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(InlineKeyboardButton, self).to_array() array['text'] = u(self.text) # py2: type unicode, py3: type str if self.url is not None: array['url'] = u(self.url) # py2: type unicode, py3: type str if self.callback_data is not None: array['callback_data'] = u( self.callback_data) # py2: type unicode, py3: type str if self.switch_inline_query is not None: array['switch_inline_query'] = u( self.switch_inline_query) # py2: type unicode, py3: type str if self.switch_inline_query_current_chat is not None: array['switch_inline_query_current_chat'] = u( self.switch_inline_query_current_chat ) # py2: type unicode, py3: type str if self.callback_game is not None: array['callback_game'] = self.callback_game.to_array( ) # type CallbackGame if self.pay is not None: array['pay'] = bool(self.pay) # type bool return array
def from_array(array): """ Deserialize a new InlineKeyboardButton from a given dictionary. :return: new InlineKeyboardButton instance. :rtype: InlineKeyboardButton """ if array is None or not array: return None # end if assert_type_or_raise(array, dict, parameter_name="array") from pytgbot.api_types.receivable.updates import CallbackGame data = {} data['text'] = u(array.get('text')) data['url'] = u( array.get('url')) if array.get('url') is not None else None data['callback_data'] = u(array.get('callback_data')) if array.get( 'callback_data') is not None else None data['switch_inline_query'] = u( array.get('switch_inline_query')) if array.get( 'switch_inline_query') is not None else None data['switch_inline_query_current_chat'] = u( array.get('switch_inline_query_current_chat')) if array.get( 'switch_inline_query_current_chat') is not None else None data['callback_game'] = CallbackGame.from_array( array.get('callback_game')) if array.get( 'callback_game') is not None else None data['pay'] = bool( array.get('pay')) if array.get('pay') is not None else None instance = InlineKeyboardButton(**data) instance._raw = array return instance
def from_array(array): """ Deserialize a new Sticker from a given dictionary. :return: new Sticker instance. :rtype: Sticker """ if array is None or not array: return None # end if assert_type_or_raise(array, dict, parameter_name="array") from pytgbot.api_types.receivable.media import PhotoSize from pytgbot.api_types.receivable.stickers import MaskPosition data = {} data['file_id'] = u(array.get('file_id')) data['width'] = int(array.get('width')) data['height'] = int(array.get('height')) data['thumb'] = PhotoSize.from_array( array.get('thumb')) if array.get('thumb') is not None else None data['emoji'] = u( array.get('emoji')) if array.get('emoji') is not None else None data['set_name'] = u(array.get('set_name')) if array.get( 'set_name') is not None else None data['mask_position'] = MaskPosition.from_array( array.get('mask_position')) if array.get( 'mask_position') is not None else None data['file_size'] = int(array.get('file_size')) if array.get( 'file_size') is not None else None data['_raw'] = array return Sticker(**data)
def from_array(array): """ Deserialize a new InputMediaDocument from a given dictionary. :return: new InputMediaDocument instance. :rtype: InputMediaDocument """ if array is None or not array: return None # end if assert_type_or_raise(array, dict, parameter_name="array") from pytgbot.api_types.sendable.files import InputFile data = {} data['type'] = u(array.get('type')) data['media'] = u(array.get('media')) if array.get('thumb') is None: data['thumb'] = None elif isinstance(array.get('thumb'), InputFile): data['thumb'] = InputFile.from_array(array.get('thumb')) elif isinstance(array.get('thumb'), str): data['thumb'] = u(array.get('thumb')) else: raise TypeError( 'Unknown type, must be one of InputFile, str or None.') # end if data['caption'] = u( array.get('caption')) if array.get('caption') is not None else None data['parse_mode'] = u(array.get('parse_mode')) if array.get( 'parse_mode') is not None else None instance = InputMediaDocument(**data) instance._raw = array return instance
def to_array(self): """ Serializes this InputMediaVideo to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(InputMediaVideo, self).to_array() array['type'] = u(self.type) # py2: type unicode, py3: type str array['media'] = u(self.media) # py2: type unicode, py3: type str if self.caption is not None: array['caption'] = u( self.caption) # py2: type unicode, py3: type str if self.parse_mode is not None: array['parse_mode'] = u( self.parse_mode) # py2: type unicode, py3: type str if self.width is not None: array['width'] = int(self.width) # type int if self.height is not None: array['height'] = int(self.height) # type int if self.duration is not None: array['duration'] = int(self.duration) # type int if self.supports_streaming is not None: array['supports_streaming'] = bool( self.supports_streaming) # type bool return array
def from_array(array): """ Deserialize a new OrderInfo from a given dictionary. :return: new OrderInfo instance. :rtype: OrderInfo """ if array is None or not array: return None # end if assert_type_or_raise(array, dict, parameter_name="array") from pytgbot.api_types.receivable.payments import ShippingAddress data = {} data['name'] = u( array.get('name')) if array.get('name') is not None else None data['phone_number'] = u(array.get('phone_number')) if array.get( 'phone_number') is not None else None data['email'] = u( array.get('email')) if array.get('email') is not None else None data['shipping_address'] = ShippingAddress.from_array( array.get('shipping_address')) if array.get( 'shipping_address') is not None else None data['_raw'] = array return OrderInfo(**data)
def validate_array(array): """ Builds a new array with valid values for the InputMediaAnimation constructor. :return: new array with valid values :rtype: dict """ assert_type_or_raise(array, dict, parameter_name="array") from pytgbot.api_types.sendable.files import InputFile data = InputMediaWithThumb.validate_array(array) data['type'] = u(array.get('type')) data['media'] = u(array.get('media')) if array.get('thumb') is None: data['thumb'] = None elif isinstance(array.get('thumb'), InputFile): data['thumb'] = InputFile.from_array(array.get('thumb')) elif isinstance(array.get('thumb'), str): data['thumb'] = u(array.get('thumb')) else: raise TypeError( 'Unknown type, must be one of InputFile, str or None.') # end ifdata['caption'] = u(array.get('caption')) if array.get('caption') is not None else None data['parse_mode'] = u(array.get('parse_mode')) if array.get( 'parse_mode') is not None else None data['width'] = int( array.get('width')) if array.get('width') is not None else None data['height'] = int( array.get('height')) if array.get('height') is not None else None data['duration'] = int(array.get('duration')) if array.get( 'duration') is not None else None
def to_array(self): """ Serializes this InputMediaAudio to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(InputMediaAudio, self).to_array() # 'type' given by superclass # 'media' given by superclass if self.thumb is not None: if isinstance(self.thumb, InputFile): array['thumb'] = None # type InputFile elif isinstance(self.thumb, str): array['thumb'] = u( self.thumb) # py2: type unicode, py3: type str else: raise TypeError('Unknown type, must be one of InputFile, str.') # end if # 'caption' given by superclass # 'parse_mode' given by superclass if self.duration is not None: array['duration'] = int(self.duration) # type int if self.performer is not None: array['performer'] = u( self.performer) # py2: type unicode, py3: type str if self.title is not None: array['title'] = u(self.title) # py2: type unicode, py3: type str return array
def validate_array(array): """ Builds a new array with valid values for the EncryptedPassportElement constructor. :return: new array with valid values :rtype: dict """ assert_type_or_raise(array, dict, parameter_name="array") data = Result.validate_array(array) data['type'] = u(array.get('type')) data['hash'] = u(array.get('hash')) data['data'] = u( array.get('data')) if array.get('data') is not None else None data['phone_number'] = u(array.get('phone_number')) if array.get( 'phone_number') is not None else None data['email'] = u( array.get('email')) if array.get('email') is not None else None data['files'] = PassportFile.from_array_list( array.get('files'), list_level=1) if array.get('files') is not None else None data['front_side'] = PassportFile.from_array(array.get( 'front_side')) if array.get('front_side') is not None else None data['reverse_side'] = PassportFile.from_array( array.get('reverse_side')) if array.get( 'reverse_side') is not None else None data['selfie'] = PassportFile.from_array( array.get('selfie')) if array.get('selfie') is not None else None data['translation'] = PassportFile.from_array_list( array.get('translation'), list_level=1) if array.get('translation') is not None else None return data
def to_array(self): """ Serializes this EncryptedPassportElement to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(EncryptedPassportElement, self).to_array() array['type'] = u(self.type) # py2: type unicode, py3: type str array['hash'] = u(self.hash) # py2: type unicode, py3: type str if self.data is not None: array['data'] = u(self.data) # py2: type unicode, py3: type str if self.phone_number is not None: array['phone_number'] = u( self.phone_number) # py2: type unicode, py3: type str if self.email is not None: array['email'] = u(self.email) # py2: type unicode, py3: type str if self.files is not None: array['files'] = self._as_array( self.files) # type list of PassportFile if self.front_side is not None: array['front_side'] = self.front_side.to_array( ) # type PassportFile if self.reverse_side is not None: array['reverse_side'] = self.reverse_side.to_array( ) # type PassportFile if self.selfie is not None: array['selfie'] = self.selfie.to_array() # type PassportFile if self.translation is not None: array['translation'] = self._as_array( self.translation) # type list of PassportFile return array
def from_array(array): """ Deserialize a new PassportElementErrorFiles from a given dictionary. :return: new PassportElementErrorFiles instance. :rtype: PassportElementErrorFiles """ if array is None or not array: return None # end if assert_type_or_raise(array, dict, parameter_name="array") data = {} data['source'] = u(array.get('source')) data['type'] = u(array.get('type')) data[ 'file_hashes'] = PassportElementErrorFiles._builtin_from_array_list( required_type=unicode_type, value=array.get('file_hashes'), list_level=1) data['message'] = u(array.get('message')) instance = PassportElementErrorFiles(**data) instance._raw = array return instance
def to_array(self): """ Serializes this InputMediaAnimation to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(InputMediaAnimation, self).to_array() array['type'] = u(self.type) # py2: type unicode, py3: type str array['media'] = u(self.media) # py2: type unicode, py3: type str if self.thumb is not None: if isinstance(self.thumb, InputFile): array['thumb'] = self.thumb.to_array() # type InputFile elif isinstance(self.thumb, str): array['thumb'] = u( self.thumb) # py2: type unicode, py3: type strelse: raise TypeError('Unknown type, must be one of InputFile, str.') # end if if self.caption is not None: array['caption'] = u( self.caption) # py2: type unicode, py3: type str if self.parse_mode is not None: array['parse_mode'] = u( self.parse_mode) # py2: type unicode, py3: type str if self.width is not None: array['width'] = int(self.width) # type int if self.height is not None: array['height'] = int(self.height) # type int if self.duration is not None: array['duration'] = int(self.duration) # type int return array
def __init__(self, host="127.0.0.1", port=4458, telegram = None, pubkey_file = None, custom_cli_args = None): from .sender import Sender from .receiver import Receiver self._proc = None if telegram and pubkey_file: if host not in ["127.0.0.1", "localhost","",None]: raise ValueError("Can only start the cli at localhost. You may not provide a different host.") host = "127.0.0.1" self.startCLI(telegram=telegram, pubkey_file=pubkey_file, custom_cli_args=custom_cli_args, port=port) elif telegram is not None or pubkey_file is not None or custom_cli_args is not None: logger.warn("cli related parameter given, but not cli and pubkey path not present.") self.sender = Sender(host=host, port=port) self.receiver = Receiver(host=host, port=port) while self._proc is not None and self._proc.returncode is None: self._proc.poll() try: result = self.sender.raw(u("help"), retry_connect=False) if result and u("Prints this help") in result: logger.info("CLI available.") else: logger.warn("CLI does not responde correctly. (Debug: {})".format(result)) break except: logger.info("CLI did not responde.") sleep(1) else: raise AssertionError("CLI Process died.")
def to_array(self): array = { "type": u(self.type), "media": u(self.media), } if self.parse_mode is not None: array['parse_mode'] = u(self.parse_mode) # py2: type unicode, py3: type str # end if return array
def validate_array(array): """ Builds a new array with valid values for the BotCommand constructor. :return: new array with valid values :rtype: dict """ assert_type_or_raise(array, dict, parameter_name="array") data = Result.validate_array(array) data['command'] = u(array.get('command')) data['description'] = u(array.get('description')) return data
def validate_array(array): """ Builds a new array with valid values for the EncryptedCredentials constructor. :return: new array with valid values :rtype: dict """ assert_type_or_raise(array, dict, parameter_name="array") data = Result.validate_array(array) data['data'] = u(array.get('data')) data['hash'] = u(array.get('hash')) data['secret'] = u(array.get('secret'))
def to_array(self): """ Serializes this BotCommand to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(BotCommand, self).to_array() array['command'] = u(self.command) # py2: type unicode, py3: type str array['description'] = u( self.description) # py2: type unicode, py3: type str return array
def to_array(self): """ Serializes this EncryptedCredentials to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(EncryptedCredentials, self).to_array() array['data'] = u(self.data) # py2: type unicode, py3: type str array['hash'] = u(self.hash) # py2: type unicode, py3: type str array['secret'] = u(self.secret) # py2: type unicode, py3: type str return array
def to_array(self): """ Serializes this ShippingOption to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(ShippingOption, self).to_array() array['id'] = u(self.id) # py2: type unicode, py3: type str array['title'] = u(self.title) # py2: type unicode, py3: type str array['prices'] = self._as_array(self.prices) # type list of LabeledPrice return array
def to_array(self): """ Serializes this InputMediaPhoto to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(InputMediaPhoto, self).to_array() array['type'] = u(self.type) # py2: type unicode, py3: type str array['media'] = u(self.media) # py2: type unicode, py3: type str if self.caption is not None: array['caption'] = u(self.caption) # py2: type unicode, py3: type str return array
def to_array(self): """ Serializes this PassportElementErrorUnspecified to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(PassportElementErrorUnspecified, self).to_array() array['source'] = u(self.source) # py2: type unicode, py3: type str array['type'] = u(self.type) # py2: type unicode, py3: type str array['element_hash'] = u(self.element_hash) # py2: type unicode, py3: type str array['message'] = u(self.message) # py2: type unicode, py3: type str return array
def to_array(self): """ Serializes this PassportElementErrorFiles to a dictionary. :return: dictionary representation of this object. :rtype: dict """ array = super(PassportElementErrorFiles, self).to_array() array['source'] = u(self.source) # py2: type unicode, py3: type str array['type'] = u(self.type) # py2: type unicode, py3: type str array['file_hashes'] = self._as_array(self.file_hashes) # type list of str array['message'] = u(self.message) # py2: type unicode, py3: type str return array
def validate_array(array): """ Builds a new array with valid values for the PassportFile constructor. :return: new array with valid values :rtype: dict """ assert_type_or_raise(array, dict, parameter_name="array") data = Result.validate_array(array) data['file_id'] = u(array.get('file_id')) data['file_unique_id'] = u(array.get('file_unique_id')) data['file_size'] = int(array.get('file_size')) data['file_date'] = int(array.get('file_date'))
def validate_array(array): """ Builds a new array with valid values for the PassportElementErrorFile constructor. :return: new array with valid values :rtype: dict """ assert_type_or_raise(array, dict, parameter_name="array") data = PassportElementError.validate_array(array) data['source'] = u(array.get('source')) data['type'] = u(array.get('type')) data['file_hash'] = u(array.get('file_hash')) data['message'] = u(array.get('message'))
def _add_message(self, text): """ Appends a message to the message queue. :type text: builtins.str :return: """ try: logger.debug("Received Message: \"{str}\"".format(str=text)) json_dict = json.loads(text) message = DictObject.objectify(json_dict) message = fix_message(message) except ValueError as e: for check in fix_plain_output.all: m = check[0].match(text) if m: message = DictObject(manual_result=m.groupdict(), type=check[1]) logger.warn("Manually parsed output! This should be json!\nMessage:>{}<".format(text)) break else: logger.warn("Received message could not be parsed.\nMessage:>{}<".format(text), exc_info=True) return if self.append_json: message.merge_dict({u("json"): text}) with self._queue_access: self._queue.append(message) self._new_messages.release()
def fix_peer(peer): # rename peer_type => type if "peer_type" in peer and peer["peer_type"]: peer["type"] = peer["peer_type"] del peer["peer_type"] # add cmd field # cmd is the field you should always use when sending messages. if peer["type"] == TGL_PEER_ENCR_CHAT: assert peer["print_name"].startswith(ENCR_CHAT_PREFIX) peer["cmd"] = peer["print_name"] elif "id" in peer and peer["id"].startswith("$"): peer["cmd"] = peer["id"] # permanent-peer-ids elif peer["type"] == TGL_PEER_CHANNEL: peer["cmd"] = u("{type}#id{peer_id}").format(type=TGL_PEER_CHANNEL, peer_id=peer["peer_id"]) else: peer["cmd"] = u("{type}#{peer_id}").format(type=peer["type"], peer_id=peer["peer_id"]) # remove print_name field # create name field if "print_name" in peer: peer["name"] = peer["print_name"] # just in case everything failes. del peer["print_name"] # can contain ugly print_names like "user#123", "chat#123" or "no_spaces_just_underscores" else: peer["name"] = "" # add name field if peer["type"] == TGL_PEER_USER: if "first_name" in peer and peer["first_name"]: peer["name"] = peer["first_name"] elif "username" in peer and peer["username"]: peer["name"] = peer["username"] elif peer["type"] in [TGL_PEER_CHAT, TGL_PEER_CHANNEL]: if "title" in peer and peer["title"]: peer["name"] = peer["title"] elif peer["type"] == TGL_PEER_ENCR_CHAT: if "user" in peer and peer["user"]: if "first_name" in peer and peer["first_name"]: peer["name"] = peer["first_name"] elif "username" in peer and peer["username"]: peer["name"] = peer["username"] elif "print_name" in peer and peer["print_name"]: peer["name"] = peer["username"] # there are no other choices. else: logger.error("Unknown peer type: {type}".format(type={peer["type"]})) return peer
def _validate_input(function_name, arguments): """ This will check if the arguments fit the functions needed parameters. Returns a tuple of cli command name and the arguments formated as unicode strings. :param function_name: The name of the called function. :type function_name: str :param arguments: given arguments, as a list. :type arguments: list of str or tuple of str :returns: unicode cli command and a list of unicode parameters. :rtype: tuple of (str, list of str) """ if function_name not in functions: raise UnknownFunction(function_name) command_name = functions[function_name][FUNC_CMD] arguments_types = functions[function_name][FUNC_ARGS] """:type arguments_types: list of pytg.argument_types.Argument""" if len(arguments) > len(arguments_types): raise ValueError( "Error in function {function_name}: {expected_number} paramters expected, but {given_number} were given.".format( function_name=function_name, expected_number=len(arguments_types), given_number=len(arguments)) ) # end if i = 0 new_args = [] for func_type in arguments_types: """:type func_type: pytg.argument_types.Argument""" if i >= len(arguments): # if to many arguments if not func_type.optional: raise ValueError( "Error in function {function_name}: Not enough parameter given, {arg_name} missing. Arguments got: {arguments}".format( function_name=function_name, arguments=arguments, arg_name=str(func_type)) ) else: logger.debug("Skipping missing optional parameter #{number} {arg_name} (type {type}) in function {function_name}.".format( type=func_type.__class__.__name__, function_name=function_name, number=i, arg_name=str(func_type)) ) continue # do not increment i, we are still processing the same arg. # end if optional # end if to many arguments arg = arguments[i] logger.debug("Parsing {function_name}: Argument {arg} - {type} ({opt})".format( function_name=n(function_name), arg=n(arg), type=func_type, opt=("optional" if hasattr(func_type, "_optional") else "needed") )) # arg is the given one, which should be func_type. try: arg_value = func_type.parse(arg) except Exception as err: logger.debug("Got error", exc_info=True) if func_type.optional: logger.debug("Skipping unfitting optional parameter #{number} {param} (type {type}) in function {function_name}.".format(type=func_type.__class__.__name__, function_name=function_name, param=str(func_type), number=i)) continue # do not increment i, we are still processing the same arg. raise ValueError("Error in function {function_name}: parameter #{number} {param} is not type {type}. ({error})".format( function_name=function_name, number=i, type=func_type.__class__.__name__, param=str(func_type), error=str(err))) new_args.append(u(arg_value)) i += 1 return command_name, new_args
def success_fail(json, need_success=True): """ Will return True if json.result == "SUCCESS". If json.result was not found, and need_success is set to True, a IllegalResponseException is raised. If json.result was not found, and need_success is set to False, it will return the original json. :param json: The input to check. :type json: DictObject :keyword need_success: if true it will raise a IllegalResponseException if json.result is not found. :type need_success: bool :returns: True if json.result == "SUCCESS", or the given json if json.result is not found. :rtype: bool | DictObject """ if not need_success and not "result" in json: return json if json.result == u("SUCCESS"): return True if json.result == u("FAIL"): raise FailException(json.error_code, json.error) raise IllegalResponseException("Found: {}".format(json))
def fix_peer(peer): # add cmd field if peer["type"] == TGL_PEER_ENCR_CHAT: assert peer["print_name"].startswith(ENCR_CHAT_PREFIX) peer["cmd"] = peer["print_name"] else: peer["cmd"] = peer["type"] + u("#") + u(str(peer["id"])) # remove print_name field # create name field if "print_name" in peer: peer["name"] = peer["print_name"] # just in case everything failes. del peer["print_name"] # can contain ugly print_names like "user#123", "chat#123" or "no_spaces_just_underscores" else: peer["name"] = "" # add name field if peer["type"] == TGL_PEER_USER: if "first_name" in peer and peer["first_name"]: peer["name"] = peer["first_name"] elif "username" in peer and peer["username"]: peer["name"] = peer["username"] elif peer["type"] == TGL_PEER_CHAT: if "title" in peer and peer["title"]: peer["name"] = peer["title"] elif peer["type"] == TGL_PEER_ENCR_CHAT: if "user" in peer and peer["user"]: if "first_name" in peer and peer["first_name"]: peer["name"] = peer["first_name"] elif "username" in peer and peer["username"]: peer["name"] = peer["username"] elif "print_name" in peer and peer["print_name"]: peer["name"] = peer["username"] # there are no other choices. else: logger.error("Unknown peer type: {type}".format(type={peer["type"]})) return peer
def _build_request(cli_command, args, modifier=None): """ This function will join the cli_command with the given parameters (dynamic *args), applying the modifier. :param cli_command: the actual command :type cli_command: str :param args: The arguments for that list :type args: list of str :keyword modifier: A modifier, like [enable_preview]. They are poorly documented in the CLI. :type modifier: str """ arg_string = " ".join([u(x) for x in args]) request = " ".join([cli_command, arg_string]) if modifier: assert isinstance(modifier, str) request = " ".join([modifier, request]) request = "".join([request, "\n"]) # TODO can this be deleted? We are using sockets now... return request
def downloaded_file(json, check_files=True): """ Checks that the download was successful. :param json: The json from the cli. :type json: DictObject :keyword check_files: If it should verify the file path. :type check_files: bool :return: The file path. :rtype: str """ if "event" not in json or not json.event: raise IllegalResponseException("Has no valid event attribute.") if json.event != u("download"): raise IllegalResponseException("Download event should be 'download'.") if "result" not in json or not json.result: raise IllegalResponseException("Has no valid result attribute.") if check_files and not path.isfile(encoding.native_type(json.result)): raise IllegalResponseException("File path \"{path}\" not valid.".format(path=json.result)) else: return json.result
def _do_command(self, cli_command, args, reply_id=None, enable_preview=None, answer_timeout=default_answer_timeout, retry_connect=2): """ This function will join the cli_command with the given parameters (dynamic *args), and execute _do_send(request,**kwargs) :keyword reply_id: The message id which this command is a reply to. (will be ignored by the CLI with non-sending commands) :type reply_id: int or None :keyword enable_preview: If the URL found in a message should have a preview. (will be ignored by the CLI with non-sending commands) :type enable_preview: bool :keyword retry_connect: How often the initial connection should be retried. default: 2. Negative number means infinite. :type retry_connect: int """ reply_part = "" if reply_id: if not isinstance(reply_id, int): raise AttributeError("reply_id keyword argument is not integer.") reply_part = "[reply=%i]" % reply_id preview_part = "[enable_preview]" if enable_preview else "[disable_preview]" arg_string = " ".join([u(x) for x in args]) request = " ".join([reply_part, preview_part, cli_command, arg_string]) request = "".join([request, "\n"]) #TODO can this be deleted? result = self._do_send(request, answer_timeout=answer_timeout, retry_connect=retry_connect) return result
def _do_send(self, command, answer_timeout=default_answer_timeout, retry_connect=2): """ You can force retry with retry_connect=2 (3 tries, default settings, first try + 2 retries) retry_connect=0 , retry_connect=False and retry_connect=None means not to retry, retry_connect=True or retry_connect= -1 means to retry infinite times. :type command: builtins.str :type answer_timeout: builtins.float or builtins.int :param retry_connect: How often the initial connection should be retried. default: 2. Negative number means infinite. :type retry_connect: int :return: """ if isinstance(retry_connect, int): pass # correct elif isinstance(retry_connect, bool): if retry_connect: # True = forever retry_connect = -1 else: retry_connect = 0 elif retry_connect is None: retry_connect = 0 # not forever. else: raise ValueError("retry_connect is not type int, bool or None.") retry_connect_original = retry_connect if not isinstance(command, (text_type, binary_type)): raise TypeError("Command to send is not a unicode(?) string. (Instead of %s you used %s.) " % (str(text_type), str(type(command)))) logger.debug("Sending command >%s<" % n(command)) with self._socked_used: while not self._do_quit: if self.s: self.s.close() self.s = None self.s = socket.socket() try: self.s.connect((self.host, self.port_out)) except socket_error as error: self.s.close() if error.errno == ECONNREFUSED and not self._do_quit: if retry_connect != 0: sleep(1) if retry_connect > 0: retry_connect -= 1 continue else: raise ConnectionError("Could not establish connection to the cli port, failed after {number} tries. (called with retry_connect={retry_connect})".format(number=(retry_connect_original + 1), retry_connect=retry_connect_original)) raise error # Not the error we are looking for, re-raise except Exception as error: self.s.close() raise error logger.debug("Socket Connected.") try: self.s.sendall(b(command)) except Exception as error: self.s.close() raise error # retry? logger.debug("All Sent.") completed = -1 # -1 = answer size yet unknown, >0 = got remaining answer size buffer = b("") self.s.settimeout(answer_timeout) # in seconds. while completed != 0: try: while 1: # retry if CTRL+C'd try: answer = self.s.recv(1) # recv() returns an empty string if the remote end is closed if len(answer) == 0: raise ConnectionError("Remote end closed") break except socket_error as err: if err.errno != EINTR: raise else: logger.exception("Uncatched exception in reading answer from cli.") self.s.settimeout(max(self.default_answer_timeout, answer_timeout)) # in seconds. # If there was input the input is now either the default one or the given one, which waits longer. buffer += answer if completed < -1 and buffer[:len(_ANSWER_SYNTAX)] != _ANSWER_SYNTAX[:len(buffer)]: raise ArithmeticError("Server response does not fit.") if completed <= -1 and buffer.startswith(_ANSWER_SYNTAX) and buffer.endswith(_LINE_BREAK): completed = int(n(buffer[7:-1])) # TODO regex. buffer = b("") completed -= 1 except ConnectionError: self.s.close() raise except socket.timeout: raise NoResponse(command) except KeyboardInterrupt: logger.exception("Exception while reading the Answer for \"%s\". Got so far: >%s< of %i\n" % (n(command), n(buffer), completed)) # TODO remove me self.s.close() raise except Exception: logger.exception("Exception while reading the Answer for \"%s\". Got so far: >%s<\n" % (n(command), n(buffer))) # TODO remove me self.s.close() raise # raise error # end while completed != 0 if self.s: self.s.close() self.s = None return u(buffer) # end while not self._do_quit # end with lock if self.s: self.s.close()
def download_song(self, song_id, requested_type="mp3", cover_as_file=False): ### Prepare/Get Meta ### requested_type = u(requested_type) if self and isinstance(self, PonyFM) and self.session: json = get_json(API_URL.format(songid=song_id), cookies=self.session.cookies, verify=False) else: json = get_json(API_URL.format(songid=song_id), verify=False) ### FILE Download ### download_src = None if "formats" in json.track: for download_format in json.track.formats: logger.debug("Found {extension} download.".format(extension=download_format.extension)) if u(download_format.extension) == requested_type: download_src = download_format.url logger.debug("Got what we need. Skipping rest.") break #end if #end for #end if if download_src is None: # not found > try streams if int(json.track.is_downloadable) != 1: logger.warn("Song is marked as 'not downloadable'! The downloaded stream might be bad quality!") else: logger.warn("Did not found the requested download type, searching in the stream formats. They might be bad quality!") #end if for extension, url in json.track.streams.items(): # for python 2 this should use iteritems() ... but meh. logger.debug("Found {extension} stream.".format(extension=extension)) if u(extension) == requested_type: logger.debug("Got what we need. Skipping rest.") download_src = url break else: # neither dl, nor streams > ERROR! logger.error("Did not (at all) found requested type ({requested_type})!".format(requested_type=requested_type)) raise AssertionError("Could not find download.") # TODO: custom DL Exception #end for-else #end if assert(download_src is not None) # Got download link. # Now Download song. if self and isinstance(self, PonyFM) and self.session: file_path, file_mime = download_file(download_src, temp_folder_name=SHORT_NAME, return_mime=True, progress_bar=True, cookies=self.session.cookies, verify=False) else: file_path, file_mime = download_file(download_src, temp_folder_name=SHORT_NAME, return_mime=True, progress_bar=True, verify=False) logger.info("Downloaded mp3 from '{url}' to '{path}'".format(url=download_src, path=file_path)) if u(file_mime) not in [u("audio/mp3"),u("audio/mpeg")]: raise AssertionError("mp3 is not mp3..") # TODO: custom exception else: extension = "mp3" # very dynamic, such future-prove! ### META ### audiofile = eyed3.load(file_path) if audiofile.tag is None: audiofile.initTag() artist = u(json.track.user.name) logger.debug("") if not audiofile.tag.title: logger.debug("Title was empty.") audiofile.tag.title = u(json.track.title) overwrite_if_not(audiofile.tag, "artist", artist) overwrite_if_not(audiofile.tag, "audio_file_url", u("https://github.com/luckydonald/pon3downloader/")) overwrite_if_not(audiofile.tag, "artist_url", u(json.track.user.url)) overwrite_if_not(audiofile.tag, "genre", u(json.track.genre.name)) overwrite_if_not(audiofile.tag, "lyrics", [u(json.track.lyrics)]) overwrite_if_not(audiofile.tag, "audio_source_url", u(json.track.url)) #if audiofile.tag.comments.get(u""): # text = audiofile.tag.comments.get(u"").text # text += u("\n-----\nDownloaded from https://pony.fm/ with Pon3Downloader (https://github.com/luckydonald/pon3downloader/).") # audiofile.tag.comments.set(text) #else: audiofile.tag.comments.set(u("Downloaded from {track_url} with Pon3Downloader (https://github.com/luckydonald/pon3downloader/)".format(track_url = json.track.url))) audiofile.tag.comments.set(u("https://github.com/luckydonald/pon3downloader"), u("Downloader")) audiofile.tag.save() ### COVER ART ### if self and isinstance(self, PonyFM) and self.session: imageData, imageMine = download_file(json.track.covers.normal, return_mime=True, return_buffer=True, progress_bar=True, cookies=self.session.cookies, verify=False) else: imageData, imageMine = download_file(json.track.covers.normal, return_mime=True, return_buffer=True, progress_bar=True, verify=False) imageType = eyed3.id3.frames.ImageFrame.FRONT_COVER audiofile.tag.images.set(imageType, imageData, b(imageMine), description=u(" ")) ### SAVE ### audiofile.tag.save() logger.debug("wrote file meta.") new_file_name = "{artist} - {title}".format(artist=artist,title=json.track.title) new_file_name = do_a_filename(new_file_name) music_file_name = new_file_name + "." + extension logger.info("Renaming to '{filename}'".format(filename=music_file_name)) file_folder = os.path.dirname(file_path) music_file_path = os.path.join(file_folder, music_file_name) logger.debug("Full new path will be '{path}'.".format(path=music_file_path)) os.rename(file_path, music_file_path) if cover_as_file: logger.debug("Trying also writing the cover file.") cover_file_name = new_file_name + guess_extension(imageMine) cover_file_path = os.path.join(file_folder, cover_file_name) with open(cover_file_path, mode="wb+") as cover_file: cover_file.write(imageData) ### FAVE ### if json.track.user_data: if json.track.user_data.is_favourited == 0: if self and isinstance(self, PonyFM) and self.session and self.token: logger.debug("Favouriting it now.") self.toggle_fave(json.track.id) else: logger.debug("User is not logged in.") else: logger.info("Song already is favorite.") return music_file_path
from luckydonaldUtils.encoding import to_native as n from DictObject import DictObject from .utils import coroutine from . import fix_plain_output from .exceptions import ConnectionError from .fix_msg_array import fix_message __author__ = 'luckydonald' logger = logging.getLogger(__name__) SOCKET_SIZE = 1 << 25 BLOCK_SIZE = 256 EMPTY_UNICODE_STRING = u("") # So we don't call it every time in the if header. EMPTY_RAW_BYTE = b("") # So we don't call it every time in the if header. _REGISTER_SESSION = b("main_session\n") _ANSWER_SYNTAX = b("ANSWER ") _LINE_BREAK = b("\n") class Receiver(object): """ Start telegram client somewhere. $ ./bin/telegram-cli -P 4458 -W --json Get a telegram >>> tg = Receiver() >>> tg.start() """
def success_fail(json): if json.result == u("SUCCESS"): return True if json.result == u("FAIL"): return json raise IllegalResponseException("Found: {}".format(json))
# -*- coding: utf-8 -*- __author__ = 'luckydonald' import logging logger = logging.getLogger(__name__) from luckydonaldUtils.encoding import to_unicode as u ENCR_CHAT_PREFIX = "!_user@" TGL_PEER_CHAT = u("chat") TGL_PEER_USER = u("user") TGL_PEER_ENCR_CHAT = u("encr_chat") TGL_PEER_GEO_CHAT = u("geo_chat") # todo: does this even exists? def fix_message(message): # skip if not has message typical elements if not all(key in message for key in ["from", "to", "out"]): return message # rename from -> sender message["sender"] = fix_peer(message["from"]) del message["from"] # rename to -> receiver message["receiver"] = fix_peer(message["to"]) del message["to"] # rename out -> own message["own"] = message["out"] del message["out"]