def _prepare_request(self, command, query): """ Prepares the command url, and converts the query json. :param command: The Url command parameter :type command: str :param query: Will get json encoded. :return: params and a url, for use with requests etc. """ from pytgbot.api_types.sendable import Sendable from pytgbot.api_types import as_array import json params = {} for key in query.keys(): element = query[key] if element is not None: if isinstance(element, Sendable): params[key] = json.dumps(as_array(element)) else: params[key] = element url = self._base_url.format(api_key=n(self.api_key), command=n(command)) return url, params
def _prepare_request(self, command, query): """ :param command: The Url command parameter :type command: str :param query: will get json encoded. :type query: dict :return: """ from luckydonaldUtils.encoding import to_native as n from pytgbot.api_types.sendable import Sendable from pytgbot.api_types import as_array from DictObject import DictObject import json params = {} for key in query.keys(): element = query[key] if element is not None: if isinstance(element, Sendable): params[key] = json.dumps(as_array(element)) else: params[key] = element url = self._base_url.format(api_key=n(self.api_key), command=n(command)) return DictObject(url=url, params=params)
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 __getattr__(self, name): """ Directly pulls the content form the dict itself, works as long as _key_map is correct. >>> b = DictObject({"foo": {"lol": True}, "hello":42, "ponies":'are pretty!'}) >>> b.notexist Traceback (most recent call last): ... AttributeError: notexist >>> b = DictObject() >>> b.notexist Traceback (most recent call last): ... AttributeError: notexist """ _exception = None # py2 try: value = dict.__getattribute__( self, n(name) ) # Raise exception if not found in original dict's attributes either return value except AttributeError: try: if n(name) in self.__dict__: return self.__dict__[n(name)] if self._attribute_to_key_map: key_name = self._attribute_to_key_map[n( name)] # Check if we have this set. self.on_get(key_name) value = dict.__getitem__(self, key_name) # self[key_name] value = self.after_get(key_name, value) return value else: if not sys.version < '3': # python 2.7 raise suppress_context(AttributeError(name)) # print("_attribute_to_key_map not defined.") _exception = AttributeError(name) _exception.__cause__ = None except KeyError: if not sys.version < '3': # python 2.7 raise suppress_context(AttributeError(name)) _exception = AttributeError(name) _exception.__cause__ = None finally: if _exception: raise _exception finally: if _exception: raise _exception
def __delitem__(self, key): """ Deletes an item by key. >>> b = DictObject({"test": "123", "littlepip": 'best pony!', 'something': 'else'}) >>> del b["test"] >>> b == {'littlepip': 'best pony!', 'something': 'else'} True >>> del b.something >>> b == {'littlepip': 'best pony!'} True >>> b.clear() >>> b == {} True :param key: The key to delete. :return: Nothing. """ if self.on_del(key): attribute_name = self.get_attribute_name_by_key(key) del self._attribute_to_key_map[n(attribute_name)] dict.__delitem__(self, key) self.after_del(key)
def __setattr__(self, name, value): if name.startswith("_"): # self._attribute_to_key_map = value super(DictObject, self).__setattr__(name, value) return else: key_name = self._attribute_to_key_map[n(name)] if n( name ) in self._attribute_to_key_map else name # if there is a key representing this attribute # update this key, too value = self.on_set(name, value) self._add_to_object_part( name, value) # needed allways to keep items beeing recursive. self._attribute_to_key_map[n( name )] = key_name # needed only on adding new element. (not when updating) # object.__setattr__(self, key, value) dict.__setitem__( self, self._attribute_to_key_map[n(name)], DictObject.objectify(value)) # self[self._key_map[key]] = value self.after_set(name, value)
def iterm_show_file(filename, data=None, inline=True, width="auto", height="auto", preserve_aspect_ratio=True): """ https://iterm2.com/documentation-images.html :param filename: :param data: :param inline: :param width: :param height: :param preserve_aspect_ratio: Size: - N (Number only): N character cells. - Npx (Number + px): N pixels. - N% (Number + %): N percent of the session's width or height. - auto: The image's inherent size will be used to determine an appropriate dimension. :return: """ width = str(width) if width is not None else "auto" height = str(height) if height is not None else "auto" if data is None: data = read_file_to_buffer(filename) # end if data_bytes = data.getvalue() output = "\033]1337;File=" \ "name={filename};size={size};inline={inline};" \ "preserveAspectRatio={preserve};width={width};height={height}:{data}\a\n".format( filename=n(b64encode(b(filename))), size=len(data_bytes), inline=1 if inline else 0, width=width, height=height, preserve=1 if preserve_aspect_ratio else 0, data=n(b64encode(data_bytes)), ) #sys.stdout.write(output) return output
def do(self, command): """ Send a request to the api. :param action: :param data: :param query: :return: """ headers = {"Active-Remote": self.token, "Easter-Egg": "http://flutterb.at/4458"} url = base_url.format(command=n(command), host=self.host, port=self.port, headers=headers) r = requests.get(url, verify=False) # Allow unsigned certificates. return r
def __delattr__(self, name): """ >>> b = DictObject({"foo": {"lol": True}, "hello":42, "ponies":'are pretty!'}) >>> b._lol = "hey" >>> b._lol 'hey' >>> b['_lol'] Traceback (most recent call last): ... KeyError: '_lol' >>> del b._lol """ # object.__delattr__(self, item) if name in self.__dict__: del self.__dict__[name] if n(name) in self._attribute_to_key_map: key = self._attribute_to_key_map[n(name)] if self.on_del(key): dict.__delitem__(self, key) del self._attribute_to_key_map[n(name)] self.after_del(key)
def merge_dict(self, d): """ --------------- Merging dicts --------------- You know what is more fun than a dict? Adding more dict to it. >>> first_dict = {"best pony":'Littlepip'} >>> second_dict = {"best fiction":"Fallout: Equestria"} There we got some Dicts. Let's merge! >>> a = DictObject( first_dict ) >>> a.merge_dict( second_dict ) # doctest: +ELLIPSIS {...} but you can go all fancy and use the += operator: >>> a += {"4458":"just google it?"} >>> a == {'4458': 'just google it?', 'best fiction':'Fallout: Equestria', 'best pony': 'Littlepip'} True This will overwrite existing values. >>> other_test = DictObject( {"key":"original value"} ) >>> other_test += {"key":"changed value"} >>> other_test["key"] == 'changed value' True TypeError will be raised, if the given element is not a dict: >>> other_test += 1234 Traceback (most recent call last): ... TypeError: Argument is no dict. """ if not isinstance(d, dict): raise TypeError("Argument is no dict.") # self._dict = d for a, b in list(d.items()): attribute_name = self.get_attribute_name_by_key(a) self._add_to_object_part(a, b) self._attribute_to_key_map[n(attribute_name)] = a return self
def __setitem__(self, key, value): """ Updates the value, or creates a new item. >>> b = DictObject({"foo": {"lol": True}, "hello":42, "ponies":'are pretty!'}) >>> b["foo"] = "updated value" >>> b == {'ponies': 'are pretty!', 'foo': 'updated value', 'hello': 42} True >>> b.foo 'updated value' >>> b["foo"] 'updated value' >>> b["bar"] = "created value" >>> b == {'ponies': 'are pretty!', 'foo': 'updated value', 'bar': 'created value', 'hello': 42} True >>> b["bar"] 'created value' >>> b.bar 'created value' >>> b.barz = "more created value" >>> b["barz"] 'more created value' >>> b.barz 'more created value' >>> b.barz = "changed this." >>> b["barz"] 'changed this.' >>> b.barz 'changed this.' """ attribute_name = self.get_attribute_name_by_key(key) unique_attribute_name = attribute_name # check, if there is already a key representing this attribute if n(attribute_name ) in self._attribute_to_key_map and self._attribute_to_key_map[n( attribute_name)] != key: # This attribute is already set, but the key is not. # Now search for the next free one i = 1 while i != 0: unique_attribute_name = attribute_name + "_" + str(i) i = i + 1 if ( n(unique_attribute_name) in self._attribute_to_key_map and self._attribute_to_key_map[n(unique_attribute_name)] != key ) else 0 # if is not free name, continue to increase, # else, if is free, set to 0 to exit loop # end while logger.warn( "\nCRITICAL WARNING in DictObject: Mapped key '%s' to attribute '%s', " "because attribute '%s' was already set by key '%s'." % (key, unique_attribute_name, attribute_name, self._attribute_to_key_map[n(attribute_name)])) value = self.on_set(key, value) self._add_to_object_part(key, value) self._attribute_to_key_map[n(unique_attribute_name)] = key self.after_set(key, value)
def _receiver(self): from ..env import NODE_PORT from errno import ECONNREFUSED logger.info("Starting receiver on {host}:{port}".format( host=ServiceInfos().hostname, port=NODE_PORT)) while not self._do_quit: # retry connection self.s = socket.socket( socket.AF_INET, # Internet socket.SOCK_STREAM) # TCP try: self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.s.bind((ServiceInfos().hostname, NODE_PORT)) self.s.listen(5) logger.debug("Socket Set up.") while not self._do_quit and self.s: self.client, address = self.s.accept() buffer = _EMPTY_RAW_BYTE answer = _EMPTY_RAW_BYTE completed = -1 # -1 = answer size yet unknown, >0 = got remaining answer size while (not self._do_quit ) and self.s and self.client: # read loop while 1: # retry if CTRL+C'd try: # self.s.setblocking(True) answer = self.client.recv(1) # recv() returns an empty string if the remote end is closed if len(answer) == 0: logger.debug("Remote end closed.") self.reset_client() # end if # logger.debug("received byte: {}".format(answer)) break except socket.error as err: if self._do_quit: self.reset_client() # end if from errno import EINTR if err.errno != EINTR: # interrupted system call raise else: logger.exception( "Uncatched exception in reading message from {client}." .format(client=address)) self.reset_client() break # to the retry connection look again. # end if # end try # end while: ctrl+c protection if not self.s or not self.client: # check if socket is still open break if completed == 0: logger.debug("Hit end.") if answer != _LINE_BREAK: raise ValueError( "Message does not end with a double linebreak." ) if buffer == _EMPTY_RAW_BYTE: logger.debug("skipping second linebreak.") completed = -1 continue logger.debug( "Received Message from {client}: {buffer}". format(client=address, buffer=buffer)) text = n(buffer) if len(text) > 0 and text.strip() != "": self._add_message(text) else: logger.warn("Striped text was empty.") answer = _EMPTY_RAW_BYTE buffer = _EMPTY_RAW_BYTE # completed = 0 (unchanged) continue buffer += answer if completed < -1 and buffer[:len( _ANSWER_SYNTAX)] != _ANSWER_SYNTAX[:len(buffer )]: raise ArithmeticError( "Server response does not fit. (Got >{}<)". format(buffer)) if completed <= -1 and buffer.startswith( _ANSWER_SYNTAX) and buffer.endswith( _LINE_BREAK): completed = int(n( buffer[len(_ANSWER_SYNTAX):-1])) # TODO regex. buffer = _EMPTY_RAW_BYTE completed -= 1 # end while: read loop # end while: for connected clients except socket.error as error: # if error.errno in [ECONNREFUSED] and not self._do_quit: # continue # # end if logger.error( "Socket failed with network error: {e}\nRetrying...". format(e=error)) except Exception as error: logger.error("Socket failed: {e}\nRetrying...".format(e=error)) # end try self.reset_socket() # end while not ._do_quit: retry connection self.reset_socket()
assert isinstance(update, Update) last_update_id = update.update_id print(update) if not update.inline_query: continue query_obj = update.inline_query assert isinstance(query_obj, InlineQuery) inline_query_id = query_obj.id query = query_obj.query print(query) foo = list() foo.append(InlineQueryResultArticle( id=query+"_normal", title="test 1 (normal)", input_message_content=InputTextMessageContent(query), description='Will send {}'.format(repr(n(query))) )) foo.append(InlineQueryResultArticle( id=query+"_markdown", title="test 2 (markdown)", input_message_content=InputTextMessageContent(query, parse_mode="Markdown"), description='Will send {}'.format(repr(n(query))) )) foo.append(InlineQueryResultArticle( id=query+"_html", title="test 3 (html)", input_message_content=InputTextMessageContent(query, parse_mode="HTML"), description='Will send {}'.format(repr(n(query))) )) try: success = bot.answer_inline_query(inline_query_id, foo, cache_time=2)
def _prepare_fileupload(self, _command, _file_is_optional, file_param_name, kwargs, value): """ :param file_param_name: For what field the file should be uploaded. :type file_param_name: str :param value: File to send. You can either pass a file_id as String to resend a file file that is already on the Telegram servers, or upload a new file, specifying the file path as :class:`pytgbot.api_types.sendable.files.InputFile`. If `_file_is_optional` is set to `True`, it can also be set to `None`. :type value: pytgbot.api_types.sendable.files.InputFile | str | None :param _command: Overwrite the command to be send. Default is to convert `file_param_name` to camel case (`"voice_note"` -> `"sendVoiceNote"`) :type _command: str|None :param _file_is_optional: If the file (`value`) is allowed to be None. :type _file_is_optional: bool :param kwargs: will get json encoded. :return: The json response from the server, or, if `self.return_python_objects` is `True`, a parsed return type. :rtype: DictObject.DictObject | pytgbot.api_types.receivable.Receivable :raises TgApiTypeError, TgApiParseException, TgApiServerException: Everything from :meth:`Bot.do`, and :class:`TgApiTypeError` """ from ..api_types.sendable.files import InputFile from luckydonaldUtils.encoding import unicode_type from luckydonaldUtils.encoding import to_native as n if value is None and _file_is_optional: # Is None but set optional, so do nothing. pass elif isinstance(value, str): kwargs[file_param_name] = str(value) elif isinstance(value, unicode_type): kwargs[file_param_name] = n(value) elif isinstance(value, InputFile): files = value.get_request_files(file_param_name) if "files" in kwargs and kwargs["files"]: # already are some files there, merge them. assert isinstance(kwargs["files"], dict), \ 'The files should be of type dict, but are of type {}.'.format(type(kwargs["files"])) for key in files.keys(): assert key not in kwargs[ "files"], '{key} would be overwritten!' kwargs["files"][key] = files[key] # end for else: # no files so far kwargs["files"] = files # end if else: raise TgApiTypeError( "Parameter {key} is not type (str, {text_type}, {input_file_type}), but type {type}" .format(key=file_param_name, type=type(value), input_file_type=InputFile, text_type=unicode_type)) # end if if not _command: # command as camelCase # "voice_note" -> "sendVoiceNote" # https://stackoverflow.com/a/10984923/3423324 command = re.sub(r'(?!^)_([a-zA-Z])', lambda m: m.group(1).upper(), "send_" + file_param_name) else: command = _command # end def return command
def _receiver(self): while not self._do_quit: # retry connection self.s = socket.socket() # errors? try: self.s.connect((self.host, self.port)) except socket.error as error: self.s.close() if error.errno == ECONNREFUSED and not self._do_quit: continue 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(_REGISTER_SESSION) except Exception as error: self.s.close() raise error #retry? logger.debug("CLI session registered.") buffer = EMPTY_RAW_BYTE answer = EMPTY_RAW_BYTE completed = -1 # -1 = answer size yet unknown, >0 = got remaining answer size while not self._do_quit: # read loop while 1: #retry if CTRL+C'd try: self.s.setblocking(True) answer = self.s.recv(1) # recv() returns an empty string if the remote end is closed if len(answer) == 0: self.s.close() raise ConnectionError("Remote end closed.") break except socket.error as err: if self._do_quit: self.s.close() return if err.errno != EINTR: raise else: logger.exception( "Uncatched exception in reading answer from cli." ) self.s.close() break # to the retry connection look again. #end while: ctrl+c protection if completed == 0: logger.debug("Hit end.") if answer != _LINE_BREAK: raise ValueError( "Message does not end with a double linebreak.") if buffer == EMPTY_RAW_BYTE: logger.debug("skipping second linebreak.") completed = -1 continue logger.debug("Received Message: %s", buffer) text = n(buffer) if len(text) > 0 and text.strip() != "": self._add_message(text) else: logger.warn("Striped text was empty.") answer = EMPTY_RAW_BYTE buffer = EMPTY_RAW_BYTE #completed = 0 (unchanged) continue buffer += answer # logger.debug("{!s:<2.2s}: {!s}".format(repr(answer)[1:-1]), buffer)# Fixed mallformatting of sting. if completed < -1 and buffer[:len( _ANSWER_SYNTAX)] != _ANSWER_SYNTAX[:len(buffer)]: raise ArithmeticError( "Server response does not fit. (Got >{}<)".format( buffer)) if completed <= -1 and buffer.startswith( _ANSWER_SYNTAX) and buffer.endswith(_LINE_BREAK): completed = int(n( buffer[len(_ANSWER_SYNTAX):-1])) #TODO regex. buffer = EMPTY_RAW_BYTE completed -= 1 #end while: read loop if self.s: self.s.close() self.s = None #end while not ._do_quit: retry connection if self.s: self.s.close() self.s = None
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 short_custom_base64_url_encode(string, encode_replacements=REPLACEMENTS): base = n(urlsafe_b64encode(b(string))).rstrip("=") return multi_replace(base, encode_replacements)
def _receiver(self): while not self._do_quit: # retry connection self.s = socket.socket() # errors? try: self.s.connect((self.host, self.port)) except socket.error as error: self.s.close() if error.errno == ECONNREFUSED and not self._do_quit: continue 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(_REGISTER_SESSION) except Exception as error: self.s.close() raise error # retry? logger.debug("CLI session registered.") buffer = EMPTY_RAW_BYTE answer = EMPTY_RAW_BYTE completed = -1 # -1 = answer size yet unknown, >0 = got remaining answer size while not self._do_quit: # read loop while 1: # retry if CTRL+C'd try: self.s.setblocking(True) answer = self.s.recv(1) # recv() returns an empty string if the remote end is closed if len(answer) == 0: self.s.close() raise ConnectionError("Remote end closed.") break except socket.error as err: if self._do_quit: self.s.close() return if err.errno != EINTR: raise else: logger.exception("Uncatched exception in reading answer from cli.") self.s.close() break # to the retry connection look again. # end while: ctrl+c protection if completed == 0: logger.debug("Hit end.") if answer != _LINE_BREAK: raise ValueError("Message does not end with a double linebreak.") if buffer == EMPTY_RAW_BYTE: logger.debug("skipping second linebreak.") completed = -1 continue logger.debug("Received Message: %s", buffer) text = n(buffer) if len(text) > 0 and text.strip() != "": self._add_message(text) else: logger.warn("Striped text was empty.") answer = EMPTY_RAW_BYTE buffer = EMPTY_RAW_BYTE # completed = 0 (unchanged) continue buffer += answer # logger.debug("{!s:<2.2s}: {!s}".format(repr(answer)[1:-1]), buffer)# Fixed mallformatting of sting. if completed < -1 and buffer[:len(_ANSWER_SYNTAX)] != _ANSWER_SYNTAX[:len(buffer)]: raise ArithmeticError("Server response does not fit. (Got >{}<)".format(buffer)) if completed <= -1 and buffer.startswith(_ANSWER_SYNTAX) and buffer.endswith(_LINE_BREAK): completed = int(n(buffer[len(_ANSWER_SYNTAX):-1])) # TODO regex. buffer = EMPTY_RAW_BYTE completed -= 1 # end while: read loop if self.s: self.s.close() self.s = None # end while not ._do_quit: retry connection if self.s: self.s.close() self.s = None
last_update_id = update.update_id print(update) if not update.inline_query: continue query_obj = update.inline_query assert isinstance(query_obj, InlineQuery) inline_query_id = query_obj.id query = query_obj.query print(query) foo = list() foo.append( InlineQueryResultArticle( id=query + "_normal", title="test 1 (normal)", input_message_content=InputTextMessageContent(query), description='Will send {}'.format(repr(n(query))))) foo.append( InlineQueryResultArticle( id=query + "_markdown", title="test 2 (markdown)", input_message_content=InputTextMessageContent( query, parse_mode="Markdown"), description='Will send {}'.format(repr(n(query))))) foo.append( InlineQueryResultArticle( id=query + "_html", title="test 3 (html)", input_message_content=InputTextMessageContent( query, parse_mode="HTML"), description='Will send {}'.format(repr(n(query))))) try:
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 as error: 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 as error: 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 short_custom_base64_url_decode(base, encode_replacements=REPLACEMENTS): replacements = revert_replacements(encode_replacements) base = multi_replace(n(base), replacements) # add missing padding # http://stackoverflow.com/a/9807138 return n(urlsafe_b64decode(base + '=' * (4 - len(base) % 4)))